也许这是一个糟糕的问题,但我有一个客户端应用程序,它会向服务器发送一些命令。我为发送命令做了一个小功能,它只是等待直到通过AutoResetEvent.WaitOne()
收到消息然后将消息作为字符串返回。我经常在我的客户端应用程序中使用此功能,因为这是一种快速实现的方法。
现在我想在这个应用程序中显示一个LoadingCircle,它正在等待来自服务器的响应。我已经在消息接收函数中写了这个,它只是将控件添加到Form中。这是工作查找,但UserControl(加载圆),在几毫秒后重绘,不再重绘,因为AutoResetEvent.WaitOne()
阻止GUI线程。我知道我可以将消息接收部分移动到另一个Thread中,但我不想更改此函数的概念,因为我使用了消息接收函数而不是 150x 。
所以我的问题是:是否有一种懒惰的方法,以便它在等待时执行GUI事件,或者我可以将LoadingCircle Control的绘图部分移动到另一个线程中?
非常感谢任何帮助
答案 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;
}