在静态环境中无法访问非静态方法?

11

考虑到这段代码...

public class CalibrationViewModel : ViewModelBase
{
    private FileSystemWatcher fsw;

    public CalibrationViewModel(Calibration calibration)
    {
        fsw = new FileSystemWatcher
            {
                Path = @"C:\Users\user\Desktop\Path\ToFile\Test_1234.txt",
                Filter = @"Test_1234.txt",
                NotifyFilter = NotifyFilters.LastWrite
            };

        fsw.Changed += (o, e) =>
            {
                var lastLine = File.ReadAllLines(e.FullPath).Last();
                Dispatcher.BeginInvoke((Action<string>) WriteLineToSamplesCollection, lastLine); //line that cites error
            };
    }

    private void WriteLineToSamplesCollection(string line)
    {
        // do some work
    }
}

为什么我会收到错误信息:“在静态上下文中无法访问非静态方法BeginInvoke”?

我查看了SE上的几个示例,大多数引用了在创建对象之前尝试使用字段,就像在静态方式中尝试使用非静态字段一样,但我不明白我的代码中是什么引发了相同的错误。

最后,我该如何修复这个特定的问题/代码?

更新:更正标题以反映“方法”而不是“属性”的问题。我还添加了该类实现了ViewModelBase。

3个回答

42
如果这是 WPF,System.Windows.Threading.Dispatcher 没有静态的 BeginInvoke() 方法。
如果你想静态调用它(即不需要引用 Dispatcher 实例本身),你可以使用静态的 Dispatcher.CurrentDispatcher 属性:
Dispatcher.CurrentDispatcher.BeginInvoke(...etc);

需要注意的是,从后台线程执行此操作将不会返回对“UI线程”的Dispatcher的引用,而是创建一个与该后台线程关联的新Dispatcher实例。

访问“UI线程”的Dispatcher的更安全的方法是通过使用System.Windows.Application.Current静态属性:

Application.Current.Dispatcher.BeginInvoke(...etc);

1
请注意,您可以在没有任何“Application”对象的情况下使用WPF,在这种情况下,“Application.Current”为“null”,这意味着更安全的方式将无法工作。 - user743382
@hvd 对的,但这只应在特殊情况下发生(例如在winforms应用程序中托管WPF内容)。否则,使用常规的WPF应用程序而没有Application类的实例会带来很多问题(例如此处和与资源相关的问题)。 - Federico Berasategui
当然,同意。即使在这种情况下,如果某些代码需要一个“Application”对象,也可以在入口点显式创建一个,这将完美地工作。 - user743382
@HighCore 方法 WriteLineToSamplesCollection(string line) 负责更新视图绑定的 ObservableCollection<T>。那么我需要使用 Application.Current.Dispatcher.BeginInvoke() 吗? - Isaiah Nelson
@IsaiahNelson,是的,那么您应该继续使用 Application.Current 方法。 - Federico Berasategui
显示剩余2条评论

9

将此更改为:

Dispatcher.BeginInvoke

转换为:

Dispatcher.CurrentDispatcher.BeginInvoke

问题在于BeginInvoke是一个实例方法,需要一个实例才能访问它。然而,您当前的语法尝试以静态方式从类Dispatcher中访问BeginInvoke,这就是导致此错误的原因:

无法在静态上下文中访问非静态方法 BeginInvoke


3

这是因为Dispatcher是一个类而不是属性。您应该将CalibrationViewModel类制作为其他类的子类,该类具有Dispatcher属性。


嗯,CalibrationViewModel确实实现了一个ViewModelBase接口用于处理INPC和其他相关内容。 - Isaiah Nelson
这不是你的代码所显示的 - public class CalibrationViewModel - 你没有在那里声明任何接口实现。 - Craig Shearer

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