2

我正在尝试将 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 说明“可能不会在承诺式任务上调用 Start”。我试过不启动任务,但是 loadOperation 回调永远不会触发。

谁能看到我在这里做错了什么?

提前致谢

4

3 回答 3

1

问题解决了。在后台, DomainContext.Load() 方法已经以异步方式运行。尝试将已经异步的方法包装在任务中一定有一些冲突。

但是,即使我仍然使用下面的代码正确遵循 EAP,我仍然会收到 InvalidOperationException 的“无法在 promise 样式的任务上调用 start”

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;
}
于 2012-05-05T00:34:46.397 回答
0

试试这个

var result = await _context.LoadAsync(_context.GetPlayersQuery());
于 2012-05-04T02:26:49.177 回答
0

尝试使用

task.ContinuewWith(Action<Task<T>> continuation)

这对我有用,因为我在使用 task.Start 时也遇到了这个异常

于 2012-05-16T00:30:53.933 回答