Pergunta

I want to use ManualResetEvent instead of Thread.Sleep to prevent my UI from freeing.

This is what I have tried:

private ManualResetEvent manualResetEvent = null;

private void Form1_Load(object sender, EventArgs e)
{
    ManualResetEvent manualResetEvent = new ManualResetEvent(false);
}

And after my operation I want to wait 5 seconds:

manualResetEvent.WaitOne(5000);

My problem is that my UI is still freezing ...

Foi útil?

Solução

Now the situation is more clear.

In this case you may use backgroundworker in example define a backgroundworker in your form.

when timer event id fired you may use

'assume that backgroundworker is named "BBC"
'support cancellation task
 BBC.WorkerSupportsCancellation = True
'enable report progress 
 BBC.WorkerReportsProgress = True
'run it        
 BBC.RunWorkerAsync()

When it finish in BBC_RunWorkerCompleted or your delegate to the method you can show a message in trhead safe mode.

that's all your from wont freeze, you will be able to use as well your application and so on.I use this method for long tasks or multiple tasks like deletion and so on.You have to set your own method/logic to see if your file has been created into the folder or not.

Outras dicas

You need to create a dedicated background thread to run the sleep on in order for the UI thread to remain ublocked and free to process its messages.

Doing manualResetEvent.WaitOne(5000); on the main UI thread will always block it.

The ManualResetEvent is a thread synchronisation primitive, hence is typically used when there are 2 or more threads in action and you want to provide synchronicity between them: E.g. Thread A blocks until some action has occurred in thread B.

Here you only have one. You can run the manualResetEvent.WaitOne(5000); in another thread (e.g. Task), but you can easily just Sleep(5000) in that task/background thread as the UI thread will remain responsive anyway.

Even better would be not to sleep and wait for an event to fire from the background thread to the UI thread informing that processing is complete.

This may help you also.

You can achive your goal in this way.Locked thread is separate one in threadpool and until ti will set manualreset event all code will wait but your ui will not freeze.

Private Sub test1(ByVal obj As Object)
    If TypeOf (obj) Is ManualResetEvent Then
        Dim _wait = DirectCast(obj, ManualResetEvent)
        Thread.Sleep(5000)
        _wait.Set()
    End If
End Sub

Private Sub TestT_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    MsgBox("Operation started at " & Now)
    Dim h As New List(Of ManualResetEvent)
    Dim _wait As New ManualResetEvent(False)
    h.Add(_wait)


    ThreadPool.QueueUserWorkItem(New WaitCallback(AddressOf test1), _wait)

    WaitHandle.WaitAll(h.ToArray)
    MsgBox("Operation completed at " & Now)
 End Sub

here in c#(translate with online tools check code)

 private void test1(object obj)
 {
   if ((obj) is ManualResetEvent) {
    dynamic _wait = (ManualResetEvent)obj;
    Thread.Sleep(5000);
    _wait.Set();
   }
 }

private void TestT_Load(System.Object sender, System.EventArgs e)
{
  Interaction.MsgBox("Operation started at " + DateAndTime.Now);
  List<ManualResetEvent> h = new List<ManualResetEvent>();
  ManualResetEvent _wait = new ManualResetEvent(false);
  h.Add(_wait);


  ThreadPool.QueueUserWorkItem(new WaitCallback(test1), _wait);

  WaitHandle.WaitAll(h.ToArray());
  Interaction.MsgBox("Operation completed at " + DateAndTime.Now);
}

however I don't understand why you're blocking for X second your interface....

Try to use following:

Task.Run(() => manualResetEvent.WaitOne(5000)).Wait();
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top