【问题标题】:Non-UI "The calling thread cannot access this object because a different thread owns it"非 UI “调用线程无法访问此对象,因为不同的线程拥有它”
【发布时间】:2014-03-05 23:43:05
【问题描述】:

我有以下代码:

var queue = printer.PrintQueue;
var canPrint = ! Dispatcher.CurrentDispatcher.Invoke(()
                            => queue.IsPaperJammed || queue.IsOutOfPaper || 
                               queue.IsInError || queue.HasPaperProblem);

它抛出以下错误:

调用线程无法访问此对象,因为不同的线程拥有它

我已经在 UI 线程上尝试过(使用如上所示的调度程序),我已经在当前线程上尝试过(没有调度程序)。

有没有办法询问对象是哪个线程拥有它?

【问题讨论】:

  • 有一种方法可以确定是否需要 Dispatcher.Invoke。这会回答你的问题吗?
  • @LordTakkera - 我不确定它会不会,因为我在 Dispatcher 和 out 的情况下尝试它,但两次都失败并出现相同的错误。我的猜测是那里有一个不同的拥有线程。
  • 什么在创建printer?我不认为你可以很容易地弄清楚哪个线程拥有一个对象,但也许我们可以弄清楚哪个是。
  • 我相信您对调度员的调用会启动一个线程。 (因此,尝试使用您的队列的线程与创建它的线程是不同的线程。)我建议将队列的创建移到调用线程内部,或者将错误条件的测试移到调用之前.您正在尝试做的事情的更大样本可能会有所帮助。 (小样本没有说明为什么在这种情况下甚至会调用多线程。)
  • 我认为你问错了问题。真正的问题在于,您为什么要尝试将由不同 Dispatcher 创建的对象访问到另一个不同的 Dispatcher?

标签: c# .net wpf


【解决方案1】:

您是否尝试过不使用 CurrentDispatcher ? :

var canPrint = ! Application.Current.Dispatcher.Invoke(()
                            => queue.IsPaperJammed || queue.IsOutOfPaper || 
                               queue.IsInError || queue.HasPaperProblem);

CurrentDispatcher.Invoke() 将从当前执行的线程调用您的代码,假设本题中的 sn-p 是从非 UI 线程运行的,它是非 UI 线程。

参考资料:

【讨论】:

    【解决方案2】:

    有一种方法可以确定当前线程是否拥有控件:
    使用control.Dispatcher.CheckAccess() 检查当前线程是否拥有该控件。如果它不拥有它,则使用调度程序 InvokeAction

    【讨论】:

    • System.Printing.PrintQueue 没有 Disptacher 成员(我可以找到)。
    【解决方案3】:

    就是这么疯狂,下面的代码没用,还是抛出异常

    dlg.PrintTicket.PageMediaSize = new PageMediaSize(302.36220472, int.MaxValue);
    dlg.PrintTicket.PageOrientation = PageOrientation.Portrait;
    

    但这段代码有效

    dlg.PrintTicket = new PrintTicket()
    {
        PageMediaSize = new PageMediaSize(273, int.MaxValue),
        PageOrientation = PageOrientation.Portrait,
    };
    

    当然,这两个代码都必须在Application.Current.Dispatcher.Invoke(() => {}),但第一个会抛出异常,第二个会解决问题

    【讨论】:

      猜你喜欢
      • 2022-01-13
      • 1970-01-01
      相关资源
      最近更新 更多