C# 如何在WPF中使用ISynchronizeInvoke接口?
我有一个这样的组件,无法更改:C# 如何在WPF中使用ISynchronizeInvoke接口?,c#,wpf,winforms,thread-synchronization,C#,Wpf,Winforms,Thread Synchronization,我有一个这样的组件,无法更改: public sealed class UFScannerManager { public UFScannerManager(ISynchronizeInvoke synInvoke); public ScannerList Scanners { get; } public event UFS_SCANNER_PROC ScannerEvent; public UFS_STATUS Init(); public UFS_S
public sealed class UFScannerManager
{
public UFScannerManager(ISynchronizeInvoke synInvoke);
public ScannerList Scanners { get; }
public event UFS_SCANNER_PROC ScannerEvent;
public UFS_STATUS Init();
public UFS_STATUS Uninit();
public UFS_STATUS Update();
[DefaultMember("Item")]
public sealed class ScannerList
{
public ScannerList(UFScannerManager Owner);
public UFScanner this[int Index] { get; }
public UFScanner this[string ScannerID] { get; }
public UFScanner this[IntPtr ScannerHandle] { get; }
public int Count { get; }
}
}
我想创建如下组件的实例:UFScannerManager(this)
,但在WPF中,我不能将passthis
作为参数调用。这里的this
表示当前窗口窗体对象,构造函数需要一个ISynchronizeInvoke sysInvoke
参数。因此,当传递此
时,扫描仪可以在Windows窗体应用程序中正确初始化。无需担心ISynchronizeInvoke
接口
UFS_STATUS ufs_res;
UFScannerManager ScannerManager;
int nScannerNumber;
ScannerManager = new UFScannerManager(this);
ufs_res = ScannerManager.Init();
nScannerNumber = ScannerManager.Scanners.Count;
但是,此代码在WPF中不起作用。问题是这条线。它不喜欢的位是此
ScannerManager = new UFScannerManager(this);
当我尝试构建时,我得到一个错误:
参数1:无法从“win_myapp”转换为“System.ComponentModel.ISynchronizeInvoke”
WPF不像
System.Windows.Forms.Form
类那样提供ISynchronizeInvoke
实现。所以你需要创建一个
幸运的是,WPF的Dispatcher
类提供了实现该功能所需的所有方法。您只需为调度程序
和调度程序操作
创建包装器/适配器
我可以告诉你怎么做。请注意,此代码不应“按原样”在生产环境中使用,因为它简化了,并且缺少异常处理
class DispatcherSynchronizeInvoke : ISynchronizeInvoke
{
private readonly Dispatcher dispatcher;
public DispatcherSynchronizeInvoke(Dispatcher dispatcher)
{
this.dispatcher = dispatcher;
}
public IAsyncResult BeginInvoke(Delegate method, object[] args)
{
// Obtaining a DispatcherOperation instance
// and wrapping it with our proxy class
return new DispatcherAsyncResult(
this.dispatcher.BeginInvoke(method, DispatcherPriority.Normal, args));
}
public object EndInvoke(IAsyncResult result)
{
DispatcherAsyncResult dispatcherResult = result as DispatcherAsyncResult;
dispatcherResult.Operation.Wait();
return dispatcherResult.Operation.Result;
}
public object Invoke(Delegate method, object[] args)
{
return dispatcher.Invoke(method, DispatcherPriority.Normal, args);
}
public bool InvokeRequired => !this.dispatcher.CheckAccess();
// We also could use the DispatcherOperation.Task directly
private class DispatcherAsyncResult : IAsyncResult
{
private readonly IAsyncResult result;
public DispatcherAsyncResult(DispatcherOperation operation)
{
this.Operation = operation;
this.result = operation.Task;
}
public DispatcherOperation Operation { get; }
public bool IsCompleted => this.result.IsCompleted;
public WaitHandle AsyncWaitHandle => this.result.AsyncWaitHandle;
public object AsyncState => this.result.AsyncState;
public bool CompletedSynchronously => this.result.CompletedSynchronously;
}
}
使用此自定义ISynchronizeInvoke
实现,您可以实例化您的类:
// Assuming you're calling this inside of a DispatcherObject, e.g. a Window
new UFScannerManager(new DispatcherSynchronizeInvoke(this.Dispatcher));
接口的优点是可以编写任意类来实现它。接口的方法很容易映射到WPF调度程序:Invoke=>Invoke,BeginInvoke=>BeginInvoke,EndInvoke=>dispatcherooperation.Wait(),InvokeRequired=>CheckAccess。