在c#中的不同线程中传递值时获取stackoverflow异常

时间:2013-09-27 07:36:49

标签: c# multithreading stack-overflow

我正在创建一个带有第三方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);
    }

有一个计时器&amp; UpdateValues()方法将在每次使用新值时调用。间隔是10秒。

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

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

3 个答案:

答案 0 :(得分:0)

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

答案 1 :(得分:0)

另一种选择是使用Task Parallel Library ,然后使用事件和委托与表单元素进行交互。

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

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();
        }
    }

答案 2 :(得分: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文档