在等待异步任务期间循环

时间:2015-11-30 23:02:13

标签: c# loops asynchronous async-await

我有以下问题。我有一个同步.Save()动作,需要花费几分钟才能完成。我无法使其成为异步(第三方库),因此为了保持UI响应,我在Task.Run()中使用它。

我想报告进度,以便用户看到正在发生 - 并且我想在状态标签中创建它 - 一个简单的旧学校附加并删除点到字符串,排序喜欢的 等等。
等待..
稍候...
等待。

我不知道如何以一种简单的方式做到这一点 - 我想到一个while循环会在任务结束时中断,但它似乎不起作用 - UI被阻止或状态标签不会更新。

我尝试了几件事,例如:

bool done = false;
            Task.Run(() =>
            {
                Exporter.DoLongSyncTask();
            }).ContinueWith(r => done = true);
            StatusLabel = ".";
            while (!done)
            {
                if (StatusLabel == "")
                    StatusLabel = ".";
                else if (StatusLabel == ".")
                    StatusLabel = "..";
                else if (StatusLabel == "..")
                    StatusLabel = "";
            }

(StatusLabel是一个实现了INotifyPropertyChanged的属性,它工作正常)

更复杂

private async Task<bool> DoTheWork()
        {

            await Task.Run(() => TheFile.Save());
            return true;
        }

            private string ReportProgress(string status)
        {
            if (status == ".")
                status = "..";
            else if (status == "..")
                status = "...";
            else if (status == "...")
                status = ".";
            MyProgress.Report(new InDesignExporterProgress { StatusInfo = status });
            return status;
        }

private string ReportProgress(string status)
{
    if (status == ".")
        status = "..";
    else if (status == "..")
        status = "...";
    else if (status == "...")
        status = ".";
    MyProgress.Report(new SomeProgressClass { StatusInfo = status });
    return status;
}       

以上从这里调用

        bool done = false;
        Task.Run(() =>
        {
            done = DoTheWork().Result;
        });
        string status = ".";
        while (!done)
        {
            status = ReportProgress(status);
        }

那么,什么是正确的方法?

2 个答案:

答案 0 :(得分:1)

要知道任务是否已完成,请检查IsCompleted属性的值。

while (!task.IsCompleted)
{
    // ...
}

但是,对于我认为你想要的,我会做这样的事情:

using (var timer = new System.Windows.Forms.Timer())
{
    timer.Tick += (s, e) =>
    {
        if (StatusLabel == "")
            StatusLabel = ".";
        else if (StatusLabel == ".")
            StatusLabel = "..";
        else if (StatusLabel == "..")
            StatusLabel = "";
    };
    timer.Interval = 100;
    timer.Enabled = true;

    await Task.Run(() => Exporter.DoLongSyncTask);
}

答案 1 :(得分:0)

我认为你使用while循环阻止你的UI线程,因为我猜它在该线程上运行。

我建议你尝试将这样的while循环和方法签名更改为async Task

public async Task DoSomething(){
        bool done = false;
        Task.Run(() =>
        {
            Exporter.DoLongSyncTask();
        }).ContinueWith(r => done = true);

        StatusLabel = ".";
        while (!done)
        {
            if (StatusLabel == "")
                StatusLabel = ".";
            else if (StatusLabel == ".")
                StatusLabel = "..";
            else if (StatusLabel == "..")
                StatusLabel = "";
            await Task.Delay(200);
        }
}