简体   繁体   English

Dispatcher是您可以在C#中传递的对象吗?

[英]Is Dispatcher an object you can pass in C#?

Is the Dispatcher an object that you can pass in C#? 分派器是否是您可以在C#中传递的对象? I have one thread that calls another thread. 我有一个线程调用另一个线程。 The second thread gives me this error when I try to do Dispatcher.CheckAccess(): 当我尝试执行Dispatcher.CheckAccess()时,第二个线程给我这个错误:

An object reference is requied for the non-static field, method or property 'System.Windows.Threading.Dispatcher.CheckAccess()'. 非静态字段,方法或属性'System.Windows.Threading.Dispatcher.CheckAccess()'需要对象引用。

So I try to create a dispatcher object in the original class and pass it to the second class, but the program doesn't like that and crashes. 因此,我尝试在原始类中创建一个调度程序对象,并将其传递给第二个类,但是程序不喜欢这样并崩溃。

The code has the general structure: 该代码具有以下一般结构:

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
  }
}

I have corrected the error by replacing Dispatcher.CheckAccess() with Dispatcher.Currentdispatcher.CheckAccess(), but why can't I just create a dispatcher object? 我已通过用Dispatcher.Currentdispatcher.CheckAccess()替换Dispatcher.CheckAccess()纠正了该错误,但是为什么我不能只创建一个调度程序对象?

A dispatcher can be passed around just like any other object in C#. 调度程序可以像C#中的其他任何对象一样传递。 However, a dispatcher can't be constructed because the constructor is made private: 但是,不能构造调度程序,因为构造函数是私有的:

var dispatcher = new Dispatcher(); //compile error

To pass a dispatcher around, you need to get some other already existing dispatcher. 要绕过调度程序,您需要获取其他一些已经存在的调度程序。 One option (as you noted in your updated question) is to use Dispatcher.CurrentDispatcher : 一种选择(如您在更新的问题中所指出的)是使用Dispatcher.CurrentDispatcher

var dispatcher = Dispatcher.CurrentDispatcher;
SomeFunction(dispatcher);

This creates a reference to Dispatcher.CurrentDispatcher which can be stored and passed around. 这将创建对Dispatcher.CurrentDispatcher的引用,该引用可以存储和传递。

In one of my own projects, I use a dispatcher to avoid errors like "The calling thread cannot access this object because a different thread owns it". 在我自己的项目中,我使用一个调度程序来避免出现诸如“调用线程无法访问该对象,因为另一个线程拥有该对象”之类的错误。 This is because in this particular class I have, it is possible for a background thread to attempt to do an operation on an object created on the UI thread. 这是因为在我拥有的这个特定类中,后台线程可能会尝试对在UI线程上创建的对象进行操作。 I am guessing you have a similar issue. 我猜你有一个类似的问题。

Here is a minimal example of how I use it: 这是我如何使用它的一个最小示例:

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();
  }
}

This may not be the best way to use Dispatchers, but it demonstrates how you can store a reference to it as a field, just like other objects in C#. 这可能不是使用Dispatchers的最佳方法,但它演示了如何像在C#中的其他对象一样将对它的引用存储为字段。

As the error message says, to call CheckAccess() you need an instance of Dispatcher on the left side of the dot. 如错误消息所述,要调用CheckAccess()您需要在点的左侧分配一个Dispatcher的实例。 For example, a code like this would work: 例如,这样的代码将起作用:

Dispatcher dispatcher = /* something here */;
dispatcher.CheckAccess();

This explains why simply writing Dispatcher.CheckAccess() in SecondClass doesn't work. 这解释了为什么仅在SecondClass中编写Dispatcher.CheckAccess() SecondClass But then why does it work in MainView ? 但后来为什么在工作MainView Because it inherits from UserControl , which has a property called Dispatcher . 因为它继承自UserControl ,后者具有名为Dispatcher的属性。 So, when you write Dispatcher.CheckAccess() there, it's basically a shorter way of writing: 因此,在此处编写Dispatcher.CheckAccess()时,基本上是一种较短的编写方式:

UserControl control = this;
control.Dispatcher.CheckAccess();

Ok, so now you should understand why MainView works and why SecondClass doesn't. 好的,现在您应该了解MainView为何起作用,而SecondClass为什么不起作用。 The only question that remains: how to make SecondClass work? 唯一剩下的问题是:如何使SecondClass工作? What you need to do is to get access to an instance of Dispatcher . 您需要做的就是访问Dispatcher的实例。 But to answer that, I need to ask a question of you: Why are you trying to call CheckAccess() ? 但是要回答这个问题,我需要问一个问题: 为什么要尝试调用CheckAccess()

Generally, you should do this when you want to call a method on a Dispatcher -bound object and you don't know if you're on the right thread for that. 通常,当您要在Dispatcher绑定的对象上调用方法并且不知道自己是否在正确的线程上时,应该执行此操作。 But if you're in that situation, you don't need a Dispatcher , you need the Dispatcher that's associated with the object you're trying to access. 但是,如果你在这种情况下的时候,你并不需要一个 Dispatcher ,你需要 Dispatcher是与您试图访问的对象相关联。 And to get that, you should use the Dispatcher property of that object (the same property that caused the confusion above). 为此,您应该使用该对象的Dispatcher属性(导致上述混淆的相同属性)。

If you're doing something else, the answer might be different, but it's hard for me to guess what that would be. 如果您正在做其他事情,答案可能会有所不同,但是我很难猜测会是什么。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM