0

我正在使用第三方 dll 创建一个 opc 服务器。他们给出了一个示例,其中所有函数都在不同的线程上运行。这是示例,OPCServer.cs:

public static OpcServer CreateInstanceAsync()
    {
        Thread thread = new Thread(new ParameterizedThreadStart(InitializationThread));
        OpcServer opcServer = new OpcServer();
        thread.Start(opcServer);
        thread.Join();
        return opcServer;
    }
 static void InitializationThread(object arg)
    {
        ((OpcServer)arg).Initialize();
    }

    void Initialize()
    {
         //some stuff
    }

  public void UpdateValues(string[] n)
    {
    this.BeginUpdate();
    value1 = (object[])n;
    for (int i = 0; i < tag_count; i++)
    {
       this.SetTag(tag_ids[i], value1[i], Quality.Good, FileTime.UtcNow);
    }
   this.EndUpdate(false);
    }

我在 UpdateValues() 方法中遇到问题;主要形式:

    public Form1()
    {
        InitializeComponent();
        opcServer = OpcServer.CreateInstanceAsync();
        opcServer.UpdateValues(valuesInArray);
    }

有一个计时器,并且 UpdateValues() 方法将在每次刻度时调用一个新值。间隔为 10 秒。

     private void timer1_Tick(object sender, EventArgs e)
    {
        opcServer.UpdateValues(valuesInArray);
    }

该程序运行平稳了一段时间。但在那之后它显示堆栈溢出异常。,有时电脑被绞死。我不明白为什么?我该如何摆脱这个?OPCServer.cs 由第 3 方提供。我的工作是在该特定方法中传递值。每次调用该方法时我都必须创建一个新线程吗?

4

3 回答 3

0

首先你为什么在这里创建一个线程

public static OpcServer CreateInstanceAsync()
{
    Thread thread = new Thread(new ParameterizedThreadStart(InitializationThread));
    OpcServer opcServer = new OpcServer();
    thread.Start(opcServer);
    thread.Join();
    return opcServer;
}

因为我可能认为,一旦获得 OpcServer 对象,您就不想挂起主表单创建,您只是使用相同的实例在计时器中调用 UpdateValues()。

现在,当你在这个电话中堆积东西时。您要添加多少更新。

this.SetTag(tag_ids[i], value1[i], Quality.Good, FileTime.UtcNow);

必须有一些方法来删除旧/过时的标签。

检查用于释放对象的 API 文档

于 2013-09-27T09:13:35.353 回答
0

另一种选择是使用任务并行库,然后使用事件和委托与表单元素进行交互。

使用任务并行库非常简单:

foreach (DriveInfo info in DriveInfo.GetDrives())
{
    if (info.DriveType == DriveType.Fixed)
        {
             var task = Task.Factory.StartNew(() => scanFiles(findType, info.RootDirectory.Name));                        
        }
}

这将是与表单元素交互的示例:

在我的外部课程中:

/// <summary>
        /// Delegate for setting text box text
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        public delegate void TextBoxEventHandler(object sender, TextEventArgs e);
        /// <summary>
        /// Event for changing tool bar text
        /// </summary>
        public event TextBoxEventHandler ChangeTextBoxText = delegate { };
        /// <summary>
        /// Function that raises set tool bar text event
        /// </summary>
        /// <param name="s"></param>
        public void SetTextBoxText(string s)
        {
            ChangeTextBoxText(this, new TextEventArgs(s));
        }

以我的形式:

    scanner.ChangeTextBoxText += scanner_ChangeTextBoxText;

    private void scanner_ChangeTextBoxText(object sender, FS.TextEventArgs e)
    {
        addMessage(e.Message);
    }

    delegate void SetTextCallback(string text);
    private void addMessage(string message)
    {
        if (edtContents.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(addMessage);
            this.Invoke(d, new object[] { message });
        }
        else
        {
            edtContents.Text += String.Format("{0}{1}", message, Environment.NewLine);
            edtContents.SelectionStart = edtContents.Text.Length;
            edtContents.ScrollToCaret();
        }
    }
于 2013-09-27T08:46:34.847 回答
0

在运行长进程时尝试使用 BackgroundWorker 更新表单。使用 ProgressChanged 事件更新表单值,否则调用委托来更新表单控件。

于 2013-09-27T08:13:15.393 回答