【问题标题】:Calling thread cannot access this object调用线程无法访问该对象
【发布时间】:2013-03-15 07:14:06
【问题描述】:

在我的 wpf 应用程序中,我在按钮单击中添加了一段代码,如下所示:

 private void btn_convert_Click(object sender, RoutedEventArgs e)
 {
    Thread t = new Thread(new ThreadStart(WorkerMethod));
    t.SetApartmentState(ApartmentState.MTA);
    t.IsBackground = true;
    t.Start();
 }

在我的WorkerMethod() 方法中,我有一些类似于下面一行的代码:

btn_convert.Content = "Convert";

当它到达这一行时,它会抛出异常,因为调用线程无法访问该对象,因为另一个线程拥有它。

我不想使用 Dispatcher,因为它会冻结 UI。UI 应该是响应式的,所以我没有选择 Dispatcher 调用或 BeginInvoke。

请给我您宝贵的建议。

【问题讨论】:

  • “我不想使用 Dispatcher,因为它会冻结 UI” - 如果工作线程不时使用 Dispatcher,则 UI 将负责。我希望您的 WorkerMethod 不会进行批量 UI 更新。 btn_convert.Content = "Convert" 将在一毫秒内冻结 UI。
  • 可以调用异步版本的Dispatcher.BeginInvoke,而不是Invoke
  • 我认为您正在 WorkerMethod 中做一些繁重的工作,而不仅仅是 ui 更新。您应该只从 Dispatcher.Invoke 更新 UI。我不明白为什么这会造成问题
  • 直接进入视图并不是 WPF 中的最佳实践。您应该使用 MVVM 模式。看codeproject.com/Articles/81484/…

标签: c# wpf multithreading


【解决方案1】:

我不想使用 Dispatcher,因为它会冻结 UI。UI 应该是响应式的,所以我没有选择 Dispatcher 调用或 BrginInvoke。

这只是说明你对调度程序的使用不好。

必须从 UI 线程访问 UI。这并不意味着您的整个 WorkerMethod 需要在 UI 线程上运行,而是这一行:

btn_convert.Content = "Convert";

确实如此。因此,您可能希望保留当前用于启动线程的代码(您是否真的需要设置单元状态),但更改任何访问 UI 的代码以使用调度程序。例如:

Action setButtonContentAction = () => btn_convert.Content = "Convert";
Dispatcher.BeginInvoke(setButtonContentAction);

或者,取决于您的 WorkerThread 正在做什么 - 如果您使用的是 C# 5 - 您可能想要使用新的异步功能。这样可以更轻松地让 UI 在 UI 线程上工作,但这确实取决于其他情况。

【讨论】:

    【解决方案2】:

    UI 更改只能由主线程应用。您可以检查是否需要主线程调用:

    if (btn_convert.InvokeRequired)
    {
      btn_convert.Invoke((MethodInvoker)(() => btn_convert.Content = "Convert"));
    }
    

    【讨论】:

      猜你喜欢
      • 2012-03-22
      • 2013-01-14
      • 1970-01-01
      • 2013-07-31
      • 1970-01-01
      • 2021-05-12
      • 1970-01-01
      • 2016-02-13
      相关资源
      最近更新 更多