新建sl4 应用程序,在mainpage下添加代码:
<button x:name="btnthread1" click="btnthread1_click">thread1</button>
后台代码为:
private void btnthread1_click(object sender, routedeventargs e)
{
new thread(() =>
{
messagebox.show("hello world");
}).start();
}
如果你运行程序,点击按钮,会得到下面的异常。
这个问题的原因很简单:一个线程尝试调用另一个线程的方法 解决这个异常的方式很简单,
1:使用dependencyobject.dispatcher.begininvoke 方法:
private void btnthread1_click(object sender, routedeventargs e)
{
new thread(() =>
{
this.dispatcher.begininvoke(() =>
{
messagebox.show("hello world");
});
}).start();
}
2:使用
synchronizationcontext 对象
private void btnthread1_click(object sender, routedeventargs e)
{
synchronizationcontext context = synchronizationcontext.current;
new thread(() =>
{
context.post((state) =>
{
messagebox.show("hello world");
}, null);
}).start();
}
但是这两者都有一个缺陷,假设有多个线程,例如多线程的多线程:
private void btnthread1_click(object sender, routedeventargs e)
{
new thread(() =>
{
synchronizationcontext context = synchronizationcontext.current;
new thread(() =>
{
context.post((state) =>
{
messagebox.show("hello world");
}, null);
}).start();
}).start();
}
虽然这里保存了context,但是因为context并不是ui线程的synchronizationcontext,所以还是会跑出异常。
所以提出了第三种方案:
1:新建静态类uisynchronizationcontext,代码如下:
/// <summary>
/// ui线程的synchronizationcontext
/// </summary>
public static class uisynchronizationcontext
{
public static synchronizationcontext context { get; set; }
}
修改app.xaml.cs 代码的构造函数,在构造app的时候设置
uisynchronizationcontext.context = synchronizationcontext.current;
public app()
{
this.startup += this.application_startup;
this.exit += this.application_exit;
this.unhandledexception += this.application_unhandledexception;
//保存ui线程同步上小文
uisynchronizationcontext.context = synchronizationcontext.current;
initializecomponent();
}
使用的时候只需要:
private void btnthread1_click(object sender, routedeventargs e)
{
new thread(() =>
{
new thread(() =>
{
uisynchronizationcontext.context.post((state) =>
{
messagebox.show("hello world");
}, null);
}).start();
}).start();
}
其实silverlight 已经提供了相似功能的类了,它就是
system.windows.deployment
你完全可以将上面的代码修改为:
new thread(() =>
{
new thread(() =>
{
//uisynchronizationcontext.context.post((state) =>
// {
// messagebox.show("hello world");
// }, null);
system.windows.deployment.current.dispatcher.begininvoke(() =>
{
messagebox.show("hello world");
});
}).start();
}).start();