【发布时间】:2014-10-02 16:58:49
【问题描述】:
我有一个表单和一些控件:
public class Tester : Form
{
public Label Demo;
public Label GetDemo()
{
return Demo.Text;
}
}
我还有一些静态类:
public static bool Delay(Func<bool> condition)
{
bool result = false;
AutoResetEvent e = new AutoResetEvent(false);
Timer t = new Timer(delegate {
if (result = condition()) e.Set(); // wait until control property has needed value
}, e, 0, 1000);
e.WaitOne();
t.Dispose();
return result;
}
有时控制会创建新线程并调用我们的静态方法:
ThreadPool.QueueUserWorkItem(delegate {
if (Delay(() => GetDemo() == "X")) MessageBox.Show("X");
}, null);
当然,这会导致异常,因为 GetDemo 将被传递给 Delay,并将作为委托在新线程中调用。
当然可以通过Invoke调用我们的静态方法来解决:
ThreadPool.QueueUserWorkItem(delegate {
Invoke((MethodInvoker) delegate {
if (Delay(() => GetDemo() == "X")) MessageBox.Show("OK");
}
}, null);
很遗憾,我不能更改延迟的调用,我只能更改它的实现。
问题:
1) INSIDE 静态方法 Delay 需要更改哪些内容,以便 condition() 在其本机线程中执行 GetDemo 而无异常?
2) 是否可以在延迟中执行类似的操作?
SynchronizationContext.Dispatcher((Action) delegate {
if (condition()) e.Set();
});
【问题讨论】:
-
与其不断检查是否满足条件,无论代码会导致满足该条件,都应该触发一个事件,然后该代码可以添加一个事件处理程序。这将使代码更简单,并且会使程序异步,因此不会阻塞 UI 线程。
-
结果总是假的。你的意思是把它分配到某个地方吗?
-
@Dave Mackersie :抱歉,已更正,是的,它有一个任务
-
@Servy :您能否澄清一下代码的哪一部分应该触发事件?据我所知,condition() 是一个委托,它调用原始方法 GetDemo(),它看起来像一种事件模型,但这不起作用,因为任何事件都会从错误的线程调用 GetDemo()。我错过了什么吗?
-
显然调用代码在这里有问题。它不仅仅停留在您的 Delay() 方法上,在线程池线程上显示消息框也是荒谬的。在 Delay() 中解决这个问题只会造成哥特式的混乱。这不是你的错误,请继续。
标签: c# multithreading thread-safety invoke synchronous