如何使用ManualResetEvent而不冻结我的UI

时间:2014-04-08 12:05:52

标签: c# .net manualresetevent

我想使用ManualResetEvent代替Thread.Sleep来阻止我的用户界面免费使用。

这就是我的尝试:

private ManualResetEvent manualResetEvent = null;

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

在我的手术后我想等5秒钟:

manualResetEvent.WaitOne(5000);

我的问题是我的用户界面仍在冻结...

4 个答案:

答案 0 :(得分:3)

现在情况更加清晰。

在这种情况下,您可以在示例中使用backgroundworker在表单中定义backgroundworker。

当计时器事件ID被触发时,您可以使用

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

当它在BBC_RunWorkerCompleted中完成或您对该方法的委托时,您可以在trhead安全模式下显示一条消息。

这一切都是你不会冻结的,你也可以使用你的应用程序等等。我将这个方法用于长任务或删除等多个任务。你必须设置自己的方法/逻辑查看您的文件是否已创建到文件夹中。

答案 1 :(得分:1)

您需要创建一个专用的后台线程来运行睡眠,以便UI线程保持畅通无阻并可以自由处理其消息。

在主UI线程上执行manualResetEvent.WaitOne(5000);将始终阻止它。

ManualResetEvent是线程同步原语,因此通常在有2个或更多线程在运行时使用,并且您希望在它们之间提供同步性:例如。线程A阻塞直到线程B中发生某些操作。

这里你只有一个。您可以在另一个帖子中运行manualResetEvent.WaitOne(5000);(例如Task),但您可以轻松地在该任务/后台线程中休眠(5000),因为UI线程无论如何都会保持响应。

更好的方法是不要睡觉并等待event to fire from the background thread到UI线程,告知处理已完成。

This也可以为您提供帮助。

答案 2 :(得分:0)

你可以用这种方式实现目标。锁定线程在线程池中是独立的,直到ti设置manualreset事件,所有代码都会等待,但你的ui不会冻结。

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

这里是c#(用在线工具检查代码翻译)

 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);
}

但是我不明白你为什么要在你的界面上阻止X.

答案 3 :(得分:-2)

尝试使用以下内容:

Task.Run(() => manualResetEvent.WaitOne(5000)).Wait();