在 C# 中在不同线程中传递值时获取堆栈溢出异常

本文关键字:获取 栈溢出 异常 堆栈 线程 | 更新日期: 2023-09-27 18:33:10

我正在使用第三方dll创建一个opc服务器.他们举了一个例子,其中所有函数r都在不同的线程上运行。下面是示例,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);
    }

我在方法更新值()中遇到问题;在主窗体中:

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

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

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

该程序运行平稳了一段时间。 但是之后就显示堆栈溢出异常,有时PC会挂起来,我不明白为什么? 我该如何摆脱这种情况? OPCServer.cs 由第 3 个给出 party.my 工作是在该特定方法中传递值。每次调用该方法时,我都必须创建一个新线程吗?

在 C# 中在不同线程中传递值时获取堆栈溢出异常

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

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

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

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();
        }
    }
首先为什么要

在这里创建一个线程

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 文档以释放对象