【问题标题】:How Does Scoping Work for Task.Factory.Startnew?Task.Factory.Startnew 的作用域如何工作?
【发布时间】:2014-07-07 19:02:44
【问题描述】:

我有一个 Silverlight 网站,它正在调用 WCF 服务,以便它可以进行一些服务器端加载。 WCF 调用是异步的,因为它已准备好 Silverlight,所以在它完成后,我正在从 CompletedEventArgs 读取数据以加载类。但是,我不确定范围界定是如何工作的。 data 在新任务的范围内是否与外部相同?它似乎从未设置为true。我知道该服务正在运行,因为正在发生异步调用,但是我无法调试完成事件触发,因为我无法将调试器附加到“ASP.net-hosted-Silverlight”(有没有办法解决这个问题?我希望能够在托管 .aspx 时调试 Silverlight...)。 我用this link. 解决了这个问题我目前正在测试我的项目,但我仍然很好奇这个范围是如何工作的。

感谢您的帮助!

编辑:我意识到这可能是构建此功能的一种糟糕的方式,我愿意提供其他建议:)

// Objects constructor calls async WCF task, upon completion of which (grammar?)
//    sets IsComplete to true
Foo data = new Foo(param);

Task waitForComplete = Task.Factory.StartNew(() =>
    {
        while (!data.IsComplete)
        {
            // Wait 1 second, then poll again
            System.Threading.Thread.Sleep(1000 * 1);
        }
    });

Task.WaitAll(new Task[] { waitForComplete });

// Now that the task has completed, we can access its data
bar.AddRange(data.GetFoo());

【问题讨论】:

  • 您可以在任务上调用Wait,或者只是在初始线程上旋转。不清楚在这里使用Task 对您有什么作用。
  • -.- 你说得很好。它在这里对我完全没有任何作用:) 这是其中一个星期一......我将只拥有while 循环
  • @ADam 但我认为问题在于您阻塞了主线程,这可能会阻止 Foo 任务完成并设置 IsComplete...
  • 那么 Reed 的回答解释了一种更好的模式供您在这种情况下使用。设置IsComplete 时是否引发事件?
  • 只有在异步 WCF 完成的回调上会发生什么,这不是问题。请参阅我对 Reed 回答的评论。 Mike 的建议解决了这个问题。

标签: c# wcf silverlight asynchronous scope


【解决方案1】:

通常,您通过调用Task.WaitAll 阻塞了主线程。 Foo 类可能正试图将回调发布到该线程,这永远不会成功。这可以解释为什么您从未真正“完成”任务。

一般来说,一个更好的方法是尽可能避免轮询(例如,一种选择是将Task/Task<T> 暴露给调用者,因此您可以在此处附加一个延续)。但是,如果您无法更改 Foo 的实现,您可以切换它以处理将数据设置为延续而不是阻塞:

// Don't block
// Task.WaitAll(new Task[] { waitForComplete });

// Instead, schedule a continuation that runs when the task is done...
waitForComplete.ContinueWith(t =>
{
    // Now that the task has completed, we can access its data
    bar.AddRange(data.GetFoo());
}, TaskScheduler.FromCurrentSynchronizationContext());

【讨论】:

  • 总的来说这是一个很好的建议。尽管我在上面的示例中阻塞了一个单独的线程,但我绝对应该默认这样做。所以即使我们从作用域返回,在任务完成后这些对象对ContinueWith表达式是可用的吗?
  • @Adam 是的 - 你总是可以关闭 lambda 中的其他变量。范围不是您原来的问题...
  • “发布回调”是指异步任务完成吗?因为我知道这不是问题——我有一个前面的异步调用,它的完成回调 is 被调用,因为它触发了第二个异步调用(我知道要触发)。
  • @Adam 如果它使用await,那么是的,这会导致问题(前提是它没有使用ConfigureAwait(false)
  • 我仍然将其标记为正确,因为您的 cmets 回答了我关于范围界定的问题,而且它是一个可靠的答案。但是,(对于未来的读者)请注意,这不是异步 WFC 服务调用的问题。
猜你喜欢
  • 2022-11-30
  • 2012-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多