0

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

现在我想在这个应用程序中显示一个 LoadingCircle,同时它正在等待来自服务器的响应。我已经在消息接收函数中为此写了一些东西,它只是将控件添加到表单中。这是有效的发现,但是在几毫秒后重绘的 UserControl(Loading Circle) 不再重绘,因为AutoResetEvent.WaitOne()正在阻止 GUI 线程。我知道我可以将消息接收部分移动到另一个线程中,但是我不想改变这个函数的概念,因为我使用了超过150x的消息接收函数。

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

任何帮助将不胜感激

4

2 回答 2

2

您实际上已经进行了异步操作,并通过AutoResetEvent.WaitOne. 现在你想把它变回异步操作。

我的建议是将功能与 UI 分开。然后工具一个同步和一个异步选项。这样,您就可以保持一个功能齐全的应用程序,并且可以在您对 150 个需要更改的实例的代码重写期间逐步发布。

4.5 中新的 async 和 await 关键字应该可以很好地为您服务。

于 2013-01-25T19:58:34.307 回答
-2

我在这里找到了一个小修复,效果很好(我不能相信它)

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;
}
于 2013-01-26T10:43:06.823 回答