Как ждать без заморозки И ждать завершения функции - PullRequest
1 голос
/ 06 июня 2019

Я бы хотел приостановить обновление файла (может занять несколько секунд), используя цикл Thread.Sleep, который каждую секунду проверяет изменение метки времени.Однако приложение полностью зависает во время цикла сна и даже не может обновить отображение.

Я посмотрел следующий (упрощенный) код, который не останавливает программу.Но программа достигает конца (печатает «Готово») до завершения функции «Рабочий» - дождитесь завершения функции (напечатайте «Конец», прежде чем «Готово»).Сняв отметку с последней строки, чтобы дождаться окончания функции, приложение замораживается.

Есть ли лучший способ дождаться изменения файла, не замораживая приложение?Если нет, то как дождаться завершения длинной функции, не останавливая приложение И не дождавшись завершения функции, прежде чем начинать с основным кодом?

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. Готово

Ответы [ 3 ]

0 голосов
/ 06 июня 2019

Предполагая, что вы работаете с 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(); 
        }
   }
 }
0 голосов
/ 06 июня 2019

Мне нравится ждать с семафорами. Проверьте перегруженный метод 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();
        }
    }
}

0 голосов
/ 06 июня 2019

Как я уже упоминал в комментариях, правильным способом было бы использовать async / await.Код будет выглядеть так:

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

main:

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

Если вы хотите использовать ThreadPool напрямую.Основываясь на платформе, вам может потребоваться предоставить метод Dispatcher to Worker, чтобы он вызывал метод для выполнения в начальном потоке.

...