[英]IAsyncResult.AsyncWaitHandle.WaitOne() completes ahead of callback
[英]How to create an IAsyncResult that immediately completes?
我正在实现一个需要实现BeginDoSomething
和EndDoSomething
方法的接口。 然而,我的DoSomething
并不是真正的长期运行。 为简单起见,假设DoSomething
只比较两个变量并返回是否 a > b
所以我的 BeginDoSomething 应该是这样的:
protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state)
{
bool returnValue = a > b;
return ...; //what should I return here?
//The method actually already completed and I don't need to wait for anything
}
我不知道我应该返回什么。 我只实现BeginDoSomething
是因为我必须这样做,而不是因为我的方法是长时间运行的。 我需要实现我自己的IAsyncResult
吗? .NET 库中是否已有实现?
这有点快速和肮脏,但您可以实现一个实现 IAsyncResult 的类,如下所示:
public class MyAsyncResult : IAsyncResult
{
bool _result;
public MyAsyncResult(bool result)
{
_result = result;
}
public bool IsCompleted
{
get { return true; }
}
public WaitHandle AsyncWaitHandle
{
get { throw new NotImplementedException(); }
}
public object AsyncState
{
get { return _result; }
}
public bool CompletedSynchronously
{
get { return true; }
}
}
然后在你的 BeginDoSomething 中使用它,如下所示:
return new MyAsyncResult(a > b);
这样做的快速黑客方法是使用委托:
protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state)
{
bool returnValue = a > b;
Func<int,int,bool> func = (x,y) => x > y;
return func.BeginInvoke(a,b,callback,state);
}
这种方法的缺点是,如果两个线程将同时调用此方法,您需要小心,您将收到错误消息。
我不确定我是否遗漏了什么,但今天你可以只返回Task.CompletedTask
/ Task.FromResult
。 Task
实现IAsyncResult
protected override IAsyncResult BeginDoSomething(int a, int b, AsyncCallback callback, object state)
{
return Task.FromResult(a > b);
}
该IAsyncResult.IsCompleted
是理所当然true
在这里。 Func.BeginInvoke
方法不会导致 true。
我建议您按照此处的说明使用基于任务的方法创建您的实现,以防其中之一确实需要长时间运行。 如果 DoSomething 运行时间很短,您可以通过从其结果创建一个Task
来阻止它
public IAsyncResult BeginDoSomething(int a, int b,
AsyncCallback callback,
object state)
{
return Task.FromResult(DoSomething(a, b)).AsApm(callback, state);
}
public bool EndDoSomething(IAsyncResult asyncResult)
{
return ((Task<bool>)asyncResult).Result;
}
bool DoSomething(int a, int b)
{
return a > b;
}
public static IAsyncResult AsApm<T>(this Task<T> task,
AsyncCallback callback,
object state)
{
if (task == null)
throw new ArgumentNullException("task");
var tcs = new TaskCompletionSource<T>(state);
task.ContinueWith(t =>
{
if (t.IsFaulted)
tcs.TrySetException(t.Exception.InnerExceptions);
else if (t.IsCanceled)
tcs.TrySetCanceled();
else
tcs.TrySetResult(t.Result);
if (callback != null)
callback(tcs.Task);
}, TaskScheduler.Default);
return tcs.Task;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.