调用线程无法访问此对象,因为另一个线程拥有它

时间:2011-03-11 01:11:48

标签: c# wcf

我已经设置了一个在对象实例上运行的WCF主机。从WCF客户端调用以下方法时,将抛出错误“调用线程无法访问此对象,因为不同的线程拥有它”。

public List<PrintQueueData> getPrintQueues()
{
    List<PrintQueueData> resultQueues = new List<PrintQueueData>();

    List<PrintQueue> queues = queueCollection;

    foreach (PrintQueue q in queues)
    {
        // This throws an exception
        resultQueues.Add(new PrintQueueData(q.HostingPrintServer.ToString(), q.Name));

        // This does NOT throw any exceptions
        resultQueues.Add(new PrintQueueData("1", "2");
    }

    return resultQueues;
}

我该怎么做才能纠正这个错误?

编辑:queueCollection是包含此方法的类的字段。

编辑:queueCollection在此类的开头声明,它的类型是printqueue列表,与此方法中分配的内容相同。

编辑:我有一个运行的计时器使用了queueCollection,但是,我将Timer.Enabled设置为false并且错误仍然发生。

2 个答案:

答案 0 :(得分:1)

“PrintQueue”类型的行为类似于“DependencyObject”。它绑定到当前线程的“Dispatcher”,类似于WPF中的UI元素。这种方式你不能在与创建队列的线程不同的线程上使用它。您必须缓存“PrintQueueData”对象(而不是“PrintQueue”对象)或在每次方法调用时实例化“PrintQueue”。

您获得的实际异常来自“System.Windows.Threading.Dispatcher.VerifyAccess()”,由“System.Printing.PrintQueue.VerifyAccess()”调用。无论何时访问属性或打印队列的方法,都会调用后者。

答案 1 :(得分:0)

你可以试试List<PrintQueue> queues = queueCollection.ToList();或沿着这条线的东西。您想要实现的是快速创建queueCollection的副本。这应该减少队列被其他线程“锁定”的可能性,从而导致所述错误。

或者,您可以在访问queueCollection时尝试使用同步。例如:

lock (wantMyQueue)
{
    // Access queueCollection in here
}

其中wantMyQueue是一个简单的object全局变量。