【问题标题】:How to wait without freezing AND wait for the function to finish如何等待而不冻结并等待函数完成
【发布时间】:2019-06-06 12:33:10
【问题描述】:

我想使用 Thread.Sleep 循环暂停文件更新(可能需要几秒钟),该循环每秒检查时间戳更改。但是,应用程序在睡眠循环期间完全冻结,甚至无法刷新显示。

我查看了以下(简化的)代码,它不会冻结程序。但是程序在 Worker 函数结束之前到达结尾(打印“Done”) - 等待 func 完成(在“done”之前打印“end”)。未注释最后一行,等待 func 结束,冻结应用程序。

有没有更好的方法来等待文件更改而不冻结应用程序?如果没有,如何在不冻结应用程序的情况下等待一个冗长的函数完成并等待函数完成后再开始主代码?

private static ManualResetEvent resetEvent = new ManualResetEvent(false);

private void Worker(object ignored)
{
    Print("start");
    Thread.Sleep(5000);
    Print("end")
    resetEvent.Set();
}

Main:
ThreadPool.QueueUserWorkItem(new WaitCallback(Worker));
Print("Done");
//resetEvent.WaitOne();

最后一行注释的输出:

  1. 完成
  2. 开始
  3. 结束

最后一行未注释的输出: (然后应用程序冻结): 1.开始 2.结束 3. 完成

预期的,没有冻结:

  1. 开始
  2. 结束
  3. 完成

【问题讨论】:

  • 这是在控制台应用程序、winforms、WPF 中吗?
  • 请检查 async await C# 关键字。
  • 这是一个控制台应用程序

标签: c# threadpool


【解决方案1】:

正如我在 cmets 中提到的,正确的方法是使用 async/await。代码将如下所示:

private async Task Worker()
{
    Print("start");
    await Task.Delay(5000);
    Print("end");
}

主要:

public async void DoSomething()
{
    await Worker();
    Print("Done");
}

如果你想直接使用线程池。基于平台,您可能需要提供一个 Dispatcher 到 Worker 方法,以便它调用一个方法在初始线程中执行。

【讨论】:

  • 感谢伊万的快速回复。我尝试了上述方法并收到编译错误,即 await 运算符只能在异步方法中使用。有什么想法我需要更改吗?
  • @JakeH 对不起。我会在一分钟内更新代码。
【解决方案2】:

我喜欢和信号量一起等待。查看重载方法 WaitOne。

using System;
using System.Threading;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            Semaphore mutex = new Semaphore(0, 1);
            Thread t = new Thread(() => {
                Console.WriteLine("Hello from another thread");
                Console.ReadLine();
                mutex.Release();
            });
            t.Start();
            while (!mutex.WaitOne(1000))
                Console.WriteLine("Waiting " + 1 + " sec");
            Console.WriteLine("Hello from main thread");
            Console.ReadLine();
        }
    }
}

【讨论】:

    【解决方案3】:

    假设您正在使用 Winforms,一个解决方案是:

     class Foo
     {
       bool spin;
       void Worker()
       {      
           Print("start");
           ///Do job
           Print("end")
    
          spin=false;
       }
       void mainMethod()
       {    
            spin = true;
            ThreadPool.QueueUserWorkItem(new WaitCallback(Worker));
            while(spin)
            {
                 Thread.Sleep(500);
                 Application.DoEvents(); 
            }
       }
     }
    

    【讨论】:

      猜你喜欢
      • 2023-03-10
      • 2019-06-16
      • 2020-06-10
      • 2020-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多