PIC*_*ain 41 c# multithreading event-handling synchronous eventargs
我正在编写一个Visual C#程序,它在辅助线程上执行连续的操作循环.偶尔当该线程完成任务时,我希望它触发一个事件处理程序.我的程序执行此操作但触发事件处理程序时,辅助线程等待事件处理程序完成后再继续执行该线程.如何让它继续?这是我目前的结构方式......
class TestClass
{
private Thread SecondaryThread;
public event EventHandler OperationFinished;
public void StartMethod()
{
...
SecondaryThread.Start(); //start the secondary thread
}
private void SecondaryThreadMethod()
{
...
OperationFinished(null, new EventArgs());
... //This is where the program waits for whatever operations take
//place when OperationFinished is triggered.
}
}
Run Code Online (Sandbox Code Playgroud)
此代码是我的某个设备的API的一部分.当触发OperationFinished事件时,我希望客户端应用程序能够执行它所需的任何操作(即相应地更新GUI),而不会导致API操作.
另外,如果我不想将任何参数传递给事件处理程序,我的语法是否正确使用OperationFinished(null, new EventArgs())
?
STW*_*STW 58
所以你想以阻止侦听器阻止后台线程的方式引发事件?给我几分钟的时间来举起一个例子; 这很简单:-)
我们先走了:首先要注意一个重要的事情 无论何时调用BeginInvoke
都必须调用相应的EndInvoke
,否则如果调用的方法抛出异常或返回一个值,则ThreadPool线程永远不会被释放回池中,从而导致线程泄漏!
class TestHarness
{
static void Main(string[] args)
{
var raiser = new SomeClass();
// Emulate some event listeners
raiser.SomeEvent += (sender, e) => { Console.WriteLine(" Received event"); };
raiser.SomeEvent += (sender, e) =>
{
// Bad listener!
Console.WriteLine(" Blocking event");
System.Threading.Thread.Sleep(5000);
Console.WriteLine(" Finished blocking event");
};
// Listener who throws an exception
raiser.SomeEvent += (sender, e) =>
{
Console.WriteLine(" Received event, time to die!");
throw new Exception();
};
// Raise the event, see the effects
raiser.DoSomething();
Console.ReadLine();
}
}
class SomeClass
{
public event EventHandler SomeEvent;
public void DoSomething()
{
OnSomeEvent();
}
private void OnSomeEvent()
{
if (SomeEvent != null)
{
var eventListeners = SomeEvent.GetInvocationList();
Console.WriteLine("Raising Event");
for (int index = 0; index < eventListeners.Count(); index++)
{
var methodToInvoke = (EventHandler)eventListeners[index];
methodToInvoke.BeginInvoke(this, EventArgs.Empty, EndAsyncEvent, null);
}
Console.WriteLine("Done Raising Event");
}
}
private void EndAsyncEvent(IAsyncResult iar)
{
var ar = (System.Runtime.Remoting.Messaging.AsyncResult)iar;
var invokedMethod = (EventHandler)ar.AsyncDelegate;
try
{
invokedMethod.EndInvoke(iar);
}
catch
{
// Handle any exceptions that were thrown by the invoked method
Console.WriteLine("An event listener went kaboom!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
Whi*_*ght 13
使用任务并行库,现在可以执行以下操作:
Task.Factory.FromAsync( ( asyncCallback, @object ) => this.OperationFinished.BeginInvoke( this, EventArgs.Empty, asyncCallback, @object ), this.OperationFinished.EndInvoke, null );
Run Code Online (Sandbox Code Playgroud)
Ree*_*sey 12
另外,如果我不想将任何参数传递给事件处理程序,那么使用OperationFinished(null,new EventArgs())我的语法是否正确?
通常,您可以将其称为:
OperationFinished(this, EventArgs.Empty);
Run Code Online (Sandbox Code Playgroud)
您应该始终将对象作为发送方传递 - 它在模式中是预期的(尽管通常被忽略).EventArgs.Empty也比新的EventArgs()更好.
为了在单独的线程中触发它,最简单的选择可能只是使用线程池:
private void RaiseOperationFinished()
{
ThreadPool.QueueUserWorkItem( new WaitCallback( (s) =>
{
if (this.OperationFinished != null)
this.OperationFinished(this, EventArgs.Empty);
}));
}
Run Code Online (Sandbox Code Playgroud)
话虽这么说,在一个单独的线程上引发一个事件应该被彻底记录,因为它可能会导致意外的行为.
归档时间: |
|
查看次数: |
48527 次 |
最近记录: |