在Silverlight 5中使用TaskSourceCompletion时抛出异常

时间:2012-05-04 01:58:46

标签: silverlight .net-4.0 wcf-ria-services task-parallel-library

我正在尝试在任务中包装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回调永远不会触发。

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

提前致谢

3 个答案:

答案 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

时也遇到了这个异常