【发布时间】:2012-04-26 13:59:53
【问题描述】:
我知道关于这个主题有一些关于 SO 的答案,但我无法找到任何适合我的解决方案。我正在尝试从数据模板中触发的 ICommand 打开一个新窗口。 实例化新窗口时(在“new MessageWindowP”内)以下两种情况都会出现上述错误:
使用 TPL/FromCurrentSynchronizationContext 更新:有效
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var scheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(new Action<object>(CreateMessageWindow), user,CancellationToken.None, TaskCreationOptions.None,scheduler);
}
}
private void CreateMessageWindow(object o)
{
var user = (UserC)o;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
使用 ThreadStart: 更新:不推荐,请参阅 Jon 的回答
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var t = new ParameterizedThreadStart(CreateMessageWindow);
var thread = new Thread(t);
thread.SetApartmentState(ApartmentState.STA);
thread.Start(sender);
}
}
private void CreateMessageWindow(object o)
{
var user = (UserC)o;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
谢谢
编辑。根据到目前为止的响应,我想指出我还在当前调度程序上尝试了 BeginInvoke,以及在原始方法中执行代码(代码就是这样开始的)。见下文:
BeginInvoke 更新:不推荐查看 Jon 的回答
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
Dispatcher.CurrentDispatcher.BeginInvoke(new Action<object>(CreateMessageWindow), sender);
}
}
private void CreateMessageWindow(object o)
{
var user = (UserC)o;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
在同一个线程中 更新:如果你已经在 UI 线程上工作了
public class ChatUserCommand : ICommand
{
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
var messageP = new MessageWindowP();
messageP.ViewModel.Participants.Add(user);
messageP.View.Show();
}
}
}
BeginInvoke,使用对第一个/主窗口调度程序的引用 更新:工作
public void Execute(object sender)
{
if (sender is UserC)
{
var user = (UserC)sender;
GeneralManager.MainDispatcher.BeginInvoke(
DispatcherPriority.Normal,
new Action(() => this.CreateMessageWindow(user)));
}
}
其中 GeneralManager.MainDispatcher 是对我创建的第一个窗口的 Dispatcher 的引用:
[somewhere far far away]
mainP = new MainP();
MainDispatcher = mainP.View.Dispatcher;
我很茫然。
【问题讨论】:
-
在同一个线程和
BeginInvoke中调用有什么问题?您的Execute在哪个线程中运行? -
你不能像这里一样使用
Dispatcher.CurrentDispatcher。查看我的答案的更新。 -
伙计们。仍然没有运气... :( 再次查看更新。
-
您能否发布简短但完整的代码,我们可以用来重现您的问题?
-
OK svick。我将尝试从代码库中提取代码并创建一个最小的可重现项目。
标签: wpf multithreading task-parallel-library dispatcher sta