线程无法访问对象

3

我有一个用户控件添加到我的主窗口。主要的代码不断接收TCP消息并相应地与用户控件交互。其中一个由主函数调用的用户控件方法是AddMessage:

internal void AddMessage(Paragraph p)
{
    if (txtViewer.Dispatcher.CheckAccess())
    {
        txtViewer.Document.Blocks.Add(p);
    }
    else
    {
        Dispatcher.Invoke(new Action(() =>
            {
                txtViewer.Document.Blocks.Add(p);
            }
        ));
    }
}

在Dispatcher.Invoke内的代码总是会抛出InvalidOperationException异常。我查看了一些类似的问题,大多数情况下是因为没有使用Dispatcher,所以我不知道为什么我的代码无法工作。我猜想我可能使用不正确,或者这可能与在线程之间传递的Paragraph对象有关。

谢谢, Jared


你是否尝试在UI线程内调用AddMessage(而不调用Dispatcher.Invoke)以查看是否存在与线程无关的问题? - as-cii
使用BeginInvoke而不是Invoke。 - Candide
2
我绝对不是专家。之前我遇到了一个类似的问题,无法将一个从Dispatcher派生的FlowDocument异步绑定到DocumentViewer上。UI不能与另一个线程中从Dispatcher派生的对象进行通信。我必须使用XamlWriter.Save将FlowDocument序列化为字符串(不从Dispatcher派生),然后在转换器中进行反序列化。 - paparazzo
@AS-CII - 我能够在UserControl的构造函数中调用AddMessage而没有任何问题。 - Jared
@BalamBalam:这个方法真是太棒了。把它作为答案发布,我会接受的。谢谢! - Jared
3个回答

1

您在检查txtViewerDispatcher上的访问权限,但如果CheckAccess失败,则调用其他另一个Dispatcher,您对该Dispatcher一无所知。您希望改为在txtViewer.Dispatcher上调用。


@Jared:异常信息是什么?是否有内部异常,如果有,它们说了什么? - H.B.
InvalidOperationException: 由于不同的线程拥有该对象,因此调用线程无法访问该对象。 没有内部异常。 - Jared
@Jared:你确定它在调用行上吗?通常,你应该在UI线程上获取相关Dispatcher的引用,因此即使在另一个线程上调用txtViewer.Dispatcher.CheckAccess()也会非常危险,因为你是通过txtViewer访问dispatcher而不是使用直接引用。 - H.B.

1

我曾经遇到过类似的问题,无法将从Dispatcher派生的FlowDocument异步绑定到DocumentViewer。UI不能绑定到另一个线程上派生自Dispatcher的对象。我不得不使用XamlWriter.Save将FlowDocument序列化为字符串(不派生自dispatcher),然后在转换器中进行反序列化。


最终,我将IsAsynch = true转换为了BackgroundWorker,并获得了10倍的性能提升。序列化和反序列化有很多开销,而且您会失去调度程序的好处。此外,您还可以获得取消操作的功能。对于返回小字符串的费时任务来说,IsAsynch = true是最佳选择。 - paparazzo

0

这可能与对象被冻结有关。

从Freezable派生的对象的想法是,它通常处于读/写状态,但可以使用Freeze方法显式地将其置为只读状态。冻结的对象在WPF中可以更有效地使用,因为它不需要通知对象的消费者其值已更改。

WPF中的图形对象(如画笔和3D几何体)都派生自Freezable。最初未冻结,对这些对象进行更改会导致对象的消费者被通知更改。

如果您有一个从Freezable派生的对象,而您不打算更改该对象,则可以使用Freeze方法使该对象变为只读。

在冻结对象之后,如果尝试修改它,则会收到InvalidOperationException。但是,WPF在使用对象时将更加高效。

摘自此处:

http://wpf.2000things.com/tag/freezable/


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接