代码之家  ›  专栏  ›  技术社区  ›  Aaron Thomas

在不阻塞ui的情况下执行工作时循环

  •  0
  • Aaron Thomas  · 技术社区  · 8 年前

    内置的progress reporter允许更新ui元素,同时也在线程池上运行(ref here )中。这非常适合偶尔更新ui元素,我发现的所有示例都展示了这个场景。

    但是,我需要在运行cpu绑定的工作时不断更新wpf ui元素,以便它以这种方式“循环”消息,直到工作完成:

    跑步
    跑步。
    跑步..
    正在运行…
    跑步

    如何在不阻塞ui线程的情况下实现这一点?

    以下是当前的实现:

    internal async Task<bool> FireWithStatusAndWork(IProgress<string> progress) {
        var reportedProgress = "Running";
    
        bool continueReporting = true;
        bool workStarted = false;
    
        // loop through the message, but also do background work
        while (continueReporting) {
            if (!workStarted) {
                workStarted = true;
                await Task.Run(() => { model.CPUIntensiveWork(); }).ConfigureAwait(false);
                continueReporting = false;
            }
            progress.Report(reportedProgress);
            if (reportedProgress.Length < 10) reportedProgress += "."; else reportedProgress = "Running";
            Thread.Sleep(200);
        }
        return true;
    }
    

    我为另一个异步新手的问题道歉,但我试图从哲学的角度(对某些场景的正确使用,但对其他场景不适用)和实际的角度(只是让事情运行)来学习。

    我已经看透了 MS docs for TAP …但如果我错过了一些相关的东西,我会很感激,如果这是一个学习点。

    1 回复  |  直到 8 年前
        1
  •  2
  •   Camilo Terevinto Chase R Lewis    8 年前

    你的循环将只运行一次,假设你是 await ING的 Task 是的。与其等待任务立即完成,不如创建任务并定期检查其状态。

    这样的做法应该管用:

    internal async Task<bool> FireWithStatusAndWork(IProgress<string> progress) 
    {
        var reportedProgress = "Running";
    
        var task = Task.Run(() => model.CPUIntensiveWork());
    
        while (!task.IsCompleted)
        {
            progress.Report(reportedProgress);
    
            if (reportedProgress.Length < 10) 
            {
                reportedProgress += "."; 
            }
            else 
            {
                reportedProgress = "Running";        
            }
    
            await Task.Delay(200);
        }
    
        return true;
    }