我正在创建一个带有第三方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由第三方提供。我的工作是在该特定方法中传递值。每次我将调用该方法时,我是否必须创建一个新线程?
答案 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文档