【发布时间】:2009-01-02 14:30:39
【问题描述】:
Andreas Huber 对this question 的回答让我想到了使用异步委托而不是线程池来实现Concurrent<T>。但是,当AsyncCallback 传递给BeginInvoke 时,我发现很难理解发生了什么,尤其是当多个线程可以访问IAsyncResult 时。不幸的是,MSDN 或我能找到的任何地方似乎都没有涵盖这种情况。此外,我能找到的所有文章要么是在闭包和泛型可用之前编写的,要么看起来就是这样。有几个问题(我希望答案是真的,但我准备好失望了):
1) 使用闭包作为 AsyncCallback 会有什么不同吗?
(希望不是)
2)如果一个线程在AsyncWaitHandle上等待,是否会被通知
a) 在回调开始之前或
b) 完成后?
(希望是 b)
3) 当回调运行时,IsCompleted 会返回什么?我可以看到的可能性:
一)true;
b)false;
c) false 在回调调用 EndInvoke 之前,true 之后。
(希望是 b 或 c)
4) 如果在调用EndInvoke 之后某个线程在AsyncWaitHandle 上等待,会抛出DisposedObjectException 吗?
(希望不是,但我希望是的)。
如果答案如我所愿,这似乎应该可行:
public class Concurrent<T> {
private IAsyncResult _asyncResult;
private T _result;
public Concurrent(Func<T> f) { // Assume f doesn't throw exceptions
_asyncResult = f.BeginInvoke(
asyncResult => {
// Assume assignment of T is atomic
_result = f.EndInvoke(asyncResult);
}, null);
}
public T Result {
get {
if (!_asyncResult.IsCompleted)
// Is there a race condition here?
_asyncResult.AsyncWaitHandle.WaitOne();
return _result; // Assume reading of T is atomic
}
...
如果问题 1-3 的答案是我所希望的,那么据我所知,这里应该没有种族条件。
【问题讨论】:
标签: c# concurrency asynchronous delegates iasyncresult