在执行工作时循环而不阻塞UI

时间:2018-07-06 18:06:05

标签: c# wpf asynchronous

内置进度报告程序允许更新UI元素,同时还可以在线程池上运行(参考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;
}

对于另一个异步新手问题,我深表歉意,但我试图从哲学的角度(正确使用某些场景,而不是其他场景)和实践角度(只是让事情运行)来学习。 / p>

我已经浏览了MS docs for TAP ...,但是如果我错过了相关的内容,请将其作为学习重点,将不胜感激。

1 个答案:

答案 0 :(得分:2)

假设您await正在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;
}