【问题标题】:C# - receiving a file through network stream is blocking WPF UIC# - 通过网络流接收文件正在阻塞 WPF UI
【发布时间】:2018-05-20 16:53:48
【问题描述】:

我有这个接收文件的方法。

public Task Download(IProgress<int> downloadProgress)
{
    return Task.Run
    (
        async () =>
        {
            var counter = 0;

            var buffer = new byte[1024];

            while (true)
            {
                var byteCount = await _networkStream.ReadAsync(buffer, 0, buffer.Length);

                counter += byteCount;
                downloadProgress.Report(counter);

                if (byteCount != buffer.Length)
                    break;
            }
        }
    );
}

然后在 UI 中我这样称呼它:

await Download(progress);

进度只是更新标签。

当我运行时,UI 将被阻止(但一段时间后它会正确更新标签)。我不明白为什么,Task.Run() 不应该创建一个新线程吗?

请问我该如何解决这个问题?

【问题讨论】:

  • StartDownloading 方法中有什么(其他?)?另外,您是否尝试过在“等待”调用中使用 ConfigureAwait(false)?我发现this article 有时在处理异步代码时很有帮助
  • 当你使用await时,你不必怀疑UI线程被阻塞了。它完全按照它所说的去做:它是等待操作的结果。
  • @GreggL StartDownloading其实是Download方法,我编辑了我的帖子
  • @Sefe 不,它没有。 await异步的。它不会同步阻塞。它实际上是为正是这种情况而设计的;使执行不阻塞 UI 线程的异步工作更容易编写,使其看起来更像同步代码(同时仍然是异步的)。如果您想了解更多关于它的作用和工作原理的信息,请随意查看 async/await 的介绍,我真的无法像这样的评论线程中的这几个 cmets 中更详细地介绍它。
  • 可能是您经常报告进度

标签: c# wpf async-await task


【解决方案1】:

您在无限循环中调用downloadProgress.Report,执行过程中没有任何暂停。我有根据的猜测是,这意味着每次 UI 线程上的执行时间可用时,非 UI 线程都会请求一个需要 UI 线程时间的操作(根据同步上下文的要求),因此会被调用阻塞。

本质上,与其用一个长时间的执行来阻塞 UI 线程,不如用一个无休止的微小线程来阻塞它。

尝试将Thread.Sleep(10) 放入“自旋锁”while(true) { ... } 循环中,看看是否能缓解问题。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多