也许这是一个不好的问题,但我有一个客户端应用程序,它向服务器发送一些命令。我做了一个发送命令的小函数,它只是等到收到消息AutoResetEvent.WaitOne()
,然后将消息作为字符串返回。我经常在我的客户端应用程序中使用此功能,因为它是实现某事的快速方法。
现在我想在这个应用程序中显示一个 LoadingCircle,同时它正在等待来自服务器的响应。我已经在消息接收函数中为此写了一些东西,它只是将控件添加到表单中。这是有效的发现,但是在几毫秒后重绘的 UserControl(Loading Circle) 不再重绘,因为AutoResetEvent.WaitOne()
正在阻止 GUI 线程。我知道我可以将消息接收部分移动到另一个线程中,但是我不想改变这个函数的概念,因为我使用了超过150x的消息接收函数。
所以我的问题是:有没有一种懒惰的方法来做到这一点,以便它在等待时执行 GUI 事件,或者我可以将 LoadingCircle 控件的绘图部分移动到另一个线程中?
任何帮助将不胜感激
问问题
893 次
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 回答