我有一个多线程应用程序,其中每个线程都能够通过使用包含guiUpdateObjects
的共享(和线程安全)BlockingCollection来记录挂起的GUI更新。
每个guiUpdateObject
包含有关要更新的控件和要显示的内容的信息。我希望我的表单使用BlockingCollection
上存在的任何项目并相应地更新各种控件。
此设置以前在此应用程序的Java版本中运行良好,在生成线程和执行初始化任务之后,主线程在定时循环中检查项目。
我想我可以在C#中使用计时器事件做同样的事情但是在Windows窗体中给出了所有本机事件处理,我想知道是否有更好的方法。也许,有一个自定义事件?非常感谢对我当前的方法提出任何批评和/或如何在C#中最好地实现这一点的建议。
根据汉斯的建议更新:
在阅读Control.BeginInvoke()之后,我明白这将允许我将PostMessage发送到应用程序消息队列。这类似于我对BlockingCollection的使用,因为它是线程安全的,并且无需等待处理消息即可立即返回。
但是,使用BeginInvoke需要使用委托,在阅读完它们之后,我仍然对正确的实现感到困惑。我是在Form类中还是在'worker'类中声明将为gui更新生成内容的委托?如果我在Form类中声明,除非我引用Form对象,否则我的worker类将无法看到该方法。或者,如果我在worker类中声明,Form类将如何在委托方法和实际方法之间建立关联?这里有一些代码突出了我的问题:
public partial class GUI : Form
{
public GUI()
{
InitializeComponent();
Thread workerThread = new Thread(new ThreadStart(new Worker().DoWork));
workerThread.Start();
}
private delegate void AppendSysLogDelegate(string logEntry);
private void AppendSysLog(string logEntry)
{
if (this.InvokeRequired)
{
this.BeginInvoke(new AppendSysLogDelegate(AppendSysLog), new object[] { logEntry });
return;
}
systemLogger.AppendText(logEntry);
}
}
public class Worker
{
public void DoWork()
{
//what goes here to call AppendSysLog("Test log entry");
}
}
答案 0 :(得分:0)
检查这个问题,并记下优秀的答案:
Is there anything like asynchronous BlockingCollection<T>?
现在你已经使用等效的blockingCollection.TakeAsync()
,你可以在UI线程上await
结果,例如:
async void btnTest_Click(object s, EventArgs e)
{
// don't forget to add exception handling
while(true)
{
var result = await blockingCollection.TakeAsync();
this.textBox.AppendText(result.ToString());
}
}