从UI线程的任务调用Thread.Sleep(n)可以冻结UI吗?

时间:2018-06-01 12:11:00

标签: c# multithreading xamarin

以下代码抽象出我的实际任务,即遍历位图中的每个像素。

myButtonCommand.execute(async () => {
   await Task.Run(() => {
       while(i++<1000000) {
           // do some work
           if(i % 1000 == 0) // only update on every 1000th iteration
           {
               ProgressChanged.Invoke(this, i); // fire update event
               Thread.Sleep(n);
           }
       }
   });
});

提供给myButtomCommand.execute的lambda在UI线程上运行。但是由于不能保证在UI线程上运行任务,这并不意味着调用Thread.Sleep(n)可能会冻结UI线程吗?

根本问题是我需要更新进度条而不执行Thread.Sleep(n),当任务正在旋转时,UI线程被阻止。

现在,我最终做的是使用Thread.Sleep(0),因此只有在另一个线程需要运行时它才会进入休眠状态。但我不明白为什么首先使用Thread.Sleep(n)是必要的,因为至少在我的测试中,它至少在一个单独的线程上。

所以我对两件事感到困惑:

  1. 从UI线程中的任务调用Thread.Sleep(n)是否安全?
  2. 在我的示例中,为什么Thread.Sleep(n)需要更新UI才能在单独的线程上运行任务?

2 个答案:

答案 0 :(得分:1)

  

并且没有执行Thread.Sleep(n),当任务正在旋转时,UI线程被阻塞。

这意味着你在这里只是召唤了太多的Invokes GUI线程没有被“阻止”,只是过度工作。

另一种可能更好的方法

 //if(i % 1000 == 0) 
   if(i % 1000000 == 0) 

答案 1 :(得分:1)

类似,我可以向你保证用户界面不会冻结 在异步上查找进度。

await Task.Delay(500);可能就是您所需要的一切。

async Task<int> TaskDelayAsync(CancellationToken ct, IProgress<int> progress)
{ 
    int i = 0; 
    while (true)
    {               
        i++;
        //Debug.WriteLine(i);
        progress.Report(i);
        ct.ThrowIfCancellationRequested();
        await Task.Delay(500);
    }
    return i;
}