我开发了多线程应用程序,用于在线程中完成事件处理。当UI线程中的事件引发时,会创建一个执行业务逻辑并终止的线程。但是,如果工作线程中的业务逻辑代码导致另一个事件; thread在主UI线程上调用控件并继续执行。同时,UI线程为新事件处理创建新线程。这两个线程都以并行方式执行。
我想要的是,如果线程导致新事件;等待新的事件completition并继续他们的任务。应按顺序处理事件。
我的任务实际上是大型框架的一部分。简言之,应用程序通过使用反射api将控制事件绑定到目标代码。
下面的UI线程处理代码捕获事件时。
Thread workerThread = new Thread(() => executeCommandTargetAsync( ..some parameters.. ));
workerThread.Start();
Worker线程通过使用Control的InvokeRequired标志和Invoke方法与UI Thread进行通信。 处理其他线程中的事件而不是UI线程的目的阻止因长事件操作而冻结UI,例如从数据库更改组合框的数据源。
答案 0 :(得分:1)
尝试使用“AutoResetEvent”类:
AutoResetEvent resetEvent = new AutoResetEvent(false);
resetEvent.WaitOne();
//pass the resetEvent object to thread 2, and when you want to continue processing the thread 1 you use the method resetEvent.Set();
答案 1 :(得分:1)
在主UI线程中运行以下内容将是灾难性的,因为UI将被冻结且无响应。
AutoResetEvent resetEvent = new AutoResetEvent(false);
resetEvent.WaitOne();
相反,你可以使用信号和计时器。 在你的winforms应用程序中创建一个事件args队列或其他合适的包装器来捕获引发事件的本质,并在线程同步锁中包装队列和出队
在您创建的单独线程中,而不是引发事件将数据或信号排入队列。
在你的winodws表单中,应用程序有一个计时器,可以轮询队列中的任何新事件,并相应地处理这些事件。
如果您使用以下示例代码,那么: 1)当其中一个控件引发事件时,只需调用EnqueueEvent而不是启动新线程 2)在你的新线程中你要做的只是用一个新信号调用EnqueueEvent而不是引发一个事件。 当然,用适合您场景的东西替换MyEventSignal类,并将计时器代码放在实际的计时器处理程序中。
public class MyEventSignal
{
public MyEventSignal()
{
}
public MyEventSignal(object _Sender, EventArgs _Args)
{
Sender = _Sender;
Args = _Args;
}
object Sender { get; set; }
EventArgs Args { get; set; }
}
private static object syncRoot = new object();
private static Queue<MyEventSignal> eventSignalQueue = new Queue<MyEventSignal>();
public static void EnqueueEvent(MyEventSignal NewEventSignal)
{
lock (syncRoot)
{
eventSignalQueue.Enqueue(NewEventSignal);
}
}
private static MyEventSignal DequeueEvent()
{
MyEventSignal result;
result = null;
lock (syncRoot)
{
if (eventSignalQueue.Count > 0)
{
result = eventSignalQueue.Dequeue();
}
}
return result;
}
private void TimerUI_Tick(object sender, EventArgs e)
{
MyEventSignal newSignal;
newSignal = DequeueEvent();
while (newSignal != null)
{
// start new thread to do stuff based on event signal
newSignal = DequeueEvent();
}
}
private void DoStuffOnParalleThread()
{
System.Threading.ThreadStart MyThreadStart;
System.Threading.Thread MyThread;
MyThreadStart = new System.Threading.ThreadStart(WorkerThreadRoutine);
MyThread = new System.Threading.Thread(MyThreadStart);
MyThread.Start()
}
private void WorkerThreadRoutine()
{
// Do stuff
//Instead of raising an event do this of course specify your event args
// or change the MyEventSignal class to suit
Form1.EnqueueEvent(new WinApp.Form1.MyEventSignal(this, EventArgs.Empty));
}