我正在实现一个需要BeginDoSomething
和EndDoSomething
方法实现的接口。但是我的DoSomething
并没有真正长期运行。
为简单起见,假设DoSomething
仅比较两个变量并返回> B'/ P>
所以我的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库中是否已有实现?
答案 0 :(得分:5)
这有点快,很脏,但您可以实现一个实现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);
答案 1 :(得分:5)
快速入侵的方法是使用委托:
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);
}
这种方法的缺点是,如果两个线程同时调用此方法,则需要小心,否则会出错。
答案 2 :(得分:0)
我不确定是否丢失了某些内容,但是今天您可以返回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
方法不会得出正确的结果。
答案 3 :(得分:0)
我建议您遵循指示here,以便能够使用基于任务的方法创建实现,以防其中之一确实运行很长时间。如果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;
}