我正在编写一个WinForms应用程序。我将有2个线程,一个UI线程和操作线程。UI线程产生Control事件,我希望Operation线程使用它们。操作线程是自动化的,并且将在消耗新事件的同时运行用于硬件控制的任务。控制事件包括但不限于启动/停止自动化
我使用BackgroundWorker是因为我的操作线程也将以MVP架构风格更新UI。
我想什么样的例子,简化为简洁。
public class UI : Form
{
Operation _operation;
BackgroundWorker _operationBackgroundWorker;
public UI_Load(object sender, EventArgs e)
{
_operationBackgroundWorker.RunWorkerAsync();
}
private void operationBackgroundWorkerDoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
_operation.DoWorkAsync(worker);
}
private void operationBackgroundWorkerRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// Only executed if something fails.
}
private void btnStart_Click(object sender, EventArgs e)
{
/* Much later in the Application lifecycle,
* somehow trigger an event on operation thread
* to begin operation.
*/
}
}
/* The operation thread. This code must run as long as the
* application is open, or until a critical error occurs.
*/
public class Operation
{
public async Task DoWorkAsync(BackgroundWorker worker)
{
// Live as long as the application and consume
// user control events fired by UI thread.
while (!worker.CancellationPending)
{
/* Make thread "sleep" until an event is triggered.
* It should be possible to fire an event while another
* operation is in progress such as stop or manual
* override (a Queue). Operation thread also uses a
* BackgroundWorker to execute hardware commands
* to not block Event queue execution.
*/
// Example operation
foreach (var event in eventQueue)
{
switch (event)
{
case Start:
// Run concurrently, for loop moves on
// to next event.
_automationWorker.RunWorkAsync();
// Uses Control.BeginInvoke() on controls
// to not block itself.
ControlView.ChangeControlToPause();
case Pause:
PauseAutomationWorker();
ControlView.ChangeControlToResume();
case Stop:
StopAutomationWorker();
ControlView.ChangeControlToStopped();
}
}
}
}
}
我以前用async/await编写过我的应用程序,没有单独的Operation线程。这并不起作用,因为它使代码库难以维护,并且(我未能找到错误)有时会使UI挂起或不响应新的控制输入。因此,我正在寻找一个更清洁的替代品。
1条答案
按热度按时间e5nqia271#
BackgroundWorker
调用ThreadPool
上的DoWork
事件处理程序。由于您的需求是拥有一个“操作线程”,我假设该线程应该仅专用于此目的,因此您应该使用Thread
构造函数。作为将消息从UI线程传递到Operation线程的传送带,您可以使用BlockingCollection<T>
。范例:在UI线程中:
在以下形式的
FormClosing
或FormClosed
事件中:反过来说,即。将消息从操作线程传递回UI线程是另一回事。您不应该直接从Operation线程操作UI控件。您可以使用
Progress<T>
示例或Control.Invoke
/Control.BeginInvoke
方法等方法。