调度程序是可以在 C# 中传递的对象吗?
本文关键字:对象 调度程序 | 更新日期: 2023-09-27 18:32:24
调度程序是可以在 C# 中传递的对象吗?我有一个线程调用另一个线程。当我尝试执行 Dispatcher.CheckAccess() 时,第二个线程给了我此错误:
非静态字段、方法或属性"System.Windows.Threading.Dispatcher.CheckAccess()"需要对象引用。
所以我尝试在原始类中创建一个调度程序对象并将其传递给第二个类,但程序不喜欢这样并崩溃。
该代码具有以下一般结构:
public public partial class MainView : UserControl{
public myButtonClick(Event eventObj, Session session)
{
//does some stuff and invokes Dispatcher.CheckAccess()
secondClass.startProcess(passThruString);
}
}
public class SecondClass
{
public startProcess(string passThru){
//does some other stuff and calls Dispatcher.CheckAccess() which throws error
}
}
我已经通过将 Dispatcher.CheckAccess() 替换为 Dispatcher.Currentdispatcher.CheckAccess() 来更正错误,但为什么我不能只创建一个调度程序对象?
程序可以像 C# 中的任何其他对象一样传递。但是,无法构造调度程序,因为构造函数是私有的:
var dispatcher = new Dispatcher(); //compile error
要传递调度程序,您需要获取其他一些已经存在的调度程序。一种选择(如您在更新的问题中指出的)是使用 Dispatcher.CurrentDispatcher
:
var dispatcher = Dispatcher.CurrentDispatcher;
SomeFunction(dispatcher);
这将创建对可以存储和传递Dispatcher.CurrentDispatcher
的引用。
在我自己的一个项目中,我使用调度程序来避免诸如"调用线程无法访问此对象,因为其他线程拥有它"之类的错误。这是因为在我拥有的这个特定类中,后台线程可能会尝试对在 UI 线程上创建的对象执行操作。我猜你有类似的问题。
这是我如何使用它的最小示例:
public class SomeClass
{
private readonly Dispatcher _dispatcher;
public SomeClass()
{
_dispatcher = Dispatcher.CurrentDispatcher;
}
public void SomeOperation()
{
InvokeIfNeeded(() => Console.WriteLine("Something"));
}
private void InvokeIfNeeded(Action action)
{
if (_dispatcher.Thread != Thread.CurrentThread)
_dispatcher.Invoke(action);
else
action();
}
}
这可能不是使用 Dispatchers 的最佳方式,但它演示了如何将对它的引用存储为字段,就像 C# 中的其他对象一样。
正如错误消息所说,要调用CheckAccess()
,您需要在点的左侧有一个Dispatcher
实例。例如,像这样的代码可以工作:
Dispatcher dispatcher = /* something here */;
dispatcher.CheckAccess();
这就解释了为什么简单地用SecondClass
写Dispatcher.CheckAccess()
是行不通的。但是为什么它在MainView
中有效?因为它继承自UserControl
,它有一个属性叫Dispatcher
。所以,当你在那里写Dispatcher.CheckAccess()
时,它基本上是一种较短的写作方式:
UserControl control = this;
control.Dispatcher.CheckAccess();
好的,所以现在你应该明白为什么MainView
有效,为什么SecondClass
不起作用。剩下的唯一问题:如何使SecondClass
发挥作用?您需要做的是访问Dispatcher
实例。但要回答这个问题,我需要问你一个问题:你为什么要打电话给CheckAccess()
?
通常,当您想在 Dispatcher
绑定对象上调用方法并且不知道您是否在正确的线程上时,您应该这样做。但是,如果您处于这种情况,则不需要Dispatcher
,您需要与您尝试访问的对象相关联的Dispatcher
。要获得它,您应该使用该对象的 Dispatcher
属性(导致上述混淆的相同属性)。
如果你正在做别的事情,答案可能会有所不同,但我很难猜测那会是什么。