AutoResetEvent.WaitOne()时渲染Usercontrol

时间:2013-01-25 18:48:15

标签: c# .net-2.0 blocking ui-thread autoresetevent

也许这是一个糟糕的问题,但我有一个客户端应用程序,它会向服务器发送一些命令。我为发送命令做了一个小功能,它只是等待直到通过AutoResetEvent.WaitOne()收到消息然后将消息作为字符串返回。我经常在我的客户端应用程序中使用此功能,因为这是一种快速实现的方法。

现在我想在这个应用程序中显示一个LoadingCircle,它正在等待来自服务器的响应。我已经在消息接收函数中写了这个,它只是将控件添加到Form中。这是工作查找,但UserControl(加载圆),在几毫秒后重绘,不再重绘,因为AutoResetEvent.WaitOne()阻止GUI线程。我知道我可以将消息接收部分移动到另一个Thread中,但我不想更改此函数的概念,因为我使用了消息接收函数而不是 150x

所以我的问题是:是否有一种懒惰的方法,以便它在等待时执行GUI事件,或者我可以将LoadingCircle Control的绘图部分移动到另一个线程中?

非常感谢任何帮助

2 个答案:

答案 0 :(得分:2)

您基本上采取了异步操作,并通过AutoResetEvent.WaitOne将其转换为同步操作。现在你想把它变回异步操作。

我的建议是将功能与UI分开。然后使用同步和异步选项。这样您就可以保留一个功能完备的应用程序,并且可以在代码重写期间逐步释放需要更改的150个实例。

4.5中的新异步和等待关键字应该可以为您提供良好的服务。

答案 1 :(得分:-2)

我找到了here的小修补程序,效果很好(我不能相信它)

private static TimeSpan InfiniteTimeout = TimeSpan.FromMilliseconds(-1); 
private const Int32 MAX_WAIT = 100; 

public static bool Wait(WaitHandle handle, TimeSpan timeout) 
{ 
    Int32 expireTicks; 
    bool signaled; 
    Int32 waitTime; 
    bool exitLoop; 

    // guard the inputs 
    if (handle == null) { 
        throw new ArgumentNullException("handle"); 
    } 
    else if ((handle.SafeWaitHandle.IsClosed)) { 
        throw new ArgumentException("closed wait handle", "handle"); 
    } 
    else if ((handle.SafeWaitHandle.IsInvalid)) { 
        throw new ArgumentException("invalid wait handle", "handle"); 
    } 
    else if ((timeout < InfiniteTimeout)) { 
        throw new ArgumentException("invalid timeout <-1", "timeout"); 
    } 

    // wait for the signal 
    expireTicks = (int)Environment.TickCount + timeout.TotalMilliseconds; 
    do { 
        if (timeout.Equals(InfiniteTimeout)) { 
            waitTime = MAX_WAIT; 
        } 
        else { 
            waitTime = (expireTicks - Environment.TickCount); 
            if (waitTime <= 0) { 
                exitLoop = true; 
                waitTime = 0; 
            } 
            else if (waitTime > MAX_WAIT) { 
                waitTime = MAX_WAIT; 
            } 
        } 

        if ((handle.SafeWaitHandle.IsClosed)) { 
            exitLoop = true; 
        } 
        else if (handle.WaitOne(waitTime, false)) { 
            exitLoop = true; 
            signaled = true; 
        } 
        else { 
            if (Application.MessageLoop) { 
                Application.DoEvents(); 
            } 
            else { 
                Thread.Sleep(1); 
            } 
        } 
    } 
    while (!exitLoop); 

    return signaled;
}