我有一個多線程應用程序,其中每個線程都有能力通過使用包含guiUpdateObjects
的共享(和線程安全的)BlockingCollection來記錄未決的GUI更新。基於BlockingCollection更改的更新表
每個guiUpdateObject
都包含有關要更新哪個控件和要顯示的內容的信息。我希望我的表單消耗該BlockingCollection
上存在的任何項目並相應地更新各種控件。
這個設置對我以前在這個應用程序的Java版本中很有效,在這個版本中,在產生線程和執行初始化任務之後,主線程檢查定時循環上的項目。
我想我可以在C#中使用計時器事件做同樣的事情,但在Windows窗體中給出所有本機事件處理時,我想知道是否有更好的方法。也許,用自定義事件?希望對我目前的做法提出任何批評和/或建議如何最好地在C#中實現這一點。
更新基於漢斯建議:
上Control.BeginInvoke()讀取後,我明白,這將讓我PostMessage的到應用程序的消息隊列。這與我對BlockingCollection的使用類似,因爲它是線程安全的並立即返回而不等待消息被處理。
然而,利用BeginInvoke需要使用委託,並在讀完它們之後,我仍然對正確的實現感到困惑。我是否會在我的Form類或'worker'類中聲明委託,以便爲gui更新生成內容?如果我在Form類中聲明,除非我引用Form對象,否則該方法對我的工作者類將不可見。或者,如果我在工人類中聲明,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");
}
}
IMO,沒有這樣的事情作爲「C#窗體」。 –
您重新發明了Control.BeginInvoke()維護的調用隊列。是的,它後面有一個事件確保這個隊列被清空,它在內部。只需使用BeginInvoke()。在任何關於Winforms編程的介紹性文章或書籍中閱讀更多關於它的內容。 –
@HansPassant謝謝 - 在這裏有一個很好的BeginInvoke教程:http://www.codeproject.com/Articles/10311/What-s-up-with-BeginInvoke。我更新了一些關於BeginInvoke和delegates的後續問題的原始問題。 – cstack22