我有一个已订阅事件的线程池线程,并且事件处理程序在另一个线程上被触发。我的问题是 - 线程池线程什么时候会被返回到池中,或者只要事件订阅处于活动状态就会留在那里?
例如:
public class RunTasks
{
private readonly MyTask _myTask;
public RunTasks(MyTask myTask)
{
_myTask = myTask;
}
public void Execute()
{
ThreadPool.QueueUserWorkItem((ignore) => _myTask.Execute());
}
}
public class MyTask
{
private readonly IThridPartyApi _dependency;
public MyTask(IThridPartyApi dependency)
{
_dependency = dependency;
}
public void Execute()
{
_dependency.UpdateEvent -= Handler;
_dependency.UpdateEvent += Handler;
}
private void Handler(object sender, EventArgs e)
{
//raised on another thread as it's coming from a thrid party library.
}
}
public interface IThridPartyApi
{
event EventHandler<EventArgs> UpdateEvent;
}
在上面的例子中,让我们说RunTasks.Execute方法被多次调用(范围为100)并且事件处理程序被触发了50个并被延迟了接下来的50个 - 有多少活动线程将监听活动订阅?我在我的应用程序中有这个场景,所以试图确保我不是从这个实现中创建一个怪物。你能帮我解答一下这个问题吗?此外,如果这不是一个高效的实现,我怎么能修改它(不使用async,因为我们仍然没有)?请注意,Execute方法是从UI按钮处理程序触发的。
谢谢, -Mike
答案 0 :(得分:0)
代码看起来的方式,ThreadPool线程仅用于重置事件处理程序,然后将其释放回池中。事件处理程序将在任何引发UpdateEvent事件的线程中运行,即第三方API的线程。
为避免这种情况,您可以使用TaskCompletionSource将事件转换为任务。 Exposing Complex EAP operations as Tasks
部分public static Task<object> OnUpdateAsync(this IThridPartyApi dependency)
{
var tcs=new TaskCompletionSource<object>();
EventHandler handler=null;
handler=(obj,args)=>
{
dependency.UpdateEvent-=handler;
//extract the response here
tcs.SetResult(response);
}
dependency.UpdateEvent+=handler;
return tcs.Task;
}
中对此进行了描述。这样,事件处理程序将在ThreadPool线程中异步运行,并且不会阻止第三方的线程等待它。
在您的情况下,您可以创建一个类似以下的函数来返回返回的任务:
object
您可以将返回类型从{{1}}更改为您希望从第三方API获得的任何内容。