在 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 工作是在该特定方法中传递值。每次调用该方法时,我都必须创建一个新线程吗?
尝试使用后台工作线程在运行长进程时更新表单。使用 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 文档以释放对象