我正在尝试在任务中包装RIA服务中使用的事件异步编程模型。
我遵循使用TaskCompletionSource的标准方法并实现了以下扩展方法:
public static Task<IEnumerable<T>> LoadAsync<T>(this DomainContext source, EntityQuery<T> query) where T : Entity
{
TaskCompletionSource<IEnumerable<T>> taskCompletionSource = new TaskCompletionSource<IEnumerable<T>>();
source.Load(
query,
loadOperation =>
{
if (loadOperation.HasError && !loadOperation.IsErrorHandled)
{
taskCompletionSource.TrySetException(loadOperation.Error);
loadOperation.MarkErrorAsHandled();
}
else if (loadOperation.IsCanceled)
{
taskCompletionSource.TrySetCanceled();
}
else
{
taskCompletionSource.TrySetResult(loadOperation.Entities);
}
},
null);
return taskCompletionSource.Task;
}
然后我以下列方式使用它:
var task = _context.LoadAsync(_context.GetPlayersQuery());
task.Start();
task.Result;
问题是我得到一个InvalidOperationException,声明“可能不会在promise样式的任务上调用Start”。我试过没有启动任务,但是随后loadOperation回调永远不会触发。
谁能看到我在这里做错了什么?
提前致谢
答案 0 :(得分:1)
问题解决了。在引擎盖下,DomainContext.Load()方法已经以异步方式运行。尝试将已经异步的方法包装在任务中一定存在一些冲突。
但是,即使我仍然使用下面的代码正确地遵循EAP,我仍然会得到“无法在promise风格的任务上调用start的InvalidOperationException”
public static Task<IEnumerable<T>> LoadAsync<T>(this DomainContext source, EntityQuery<T> query) where T : Entity
{
TaskCompletionSource<IEnumerable<T>> taskCompletionSource = new TaskCompletionSource<IEnumerable<T>>();
var loadOperation = source.Load(query);
loadOperation.Completed += (obj, args) =>
{
if (loadOperation.HasError && !loadOperation.IsErrorHandled)
{
taskCompletionSource.TrySetException(loadOperation.Error);
loadOperation.MarkErrorAsHandled();
}
else if (loadOperation.IsCanceled)
{
taskCompletionSource.TrySetCanceled();
}
else
{
taskCompletionSource.TrySetResult(loadOperation.Entities);
}
};
return taskCompletionSource.Task;
}
答案 1 :(得分:0)
试试这个
var result = await _context.LoadAsync(_context.GetPlayersQuery());
答案 2 :(得分:0)
尝试使用
task.ContinuewWith(Action<Task<T>> continuation)
这对我有用,因为我在使用task.Start
时也遇到了这个异常