Dispatcher.CheckAccess()不是从我的控制台应用程序的工作,有没有更好的办法 [英] Dispatcher.CheckAccess() isn't working from my console application, is there a better way

查看:141
本文介绍了Dispatcher.CheckAccess()不是从我的控制台应用程序的工作,有没有更好的办法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写在WPF / VB应用程序分离的业务逻辑和用户界面为不同的项目。

业务层使用运行在不同的线程,现在,一个串口,我试着写一个命令行界面,同样的业务层,似乎当.Invoke()被调用失败。 (没有错误,只是不工作)

我是pretty的肯定,我有原因的的checkAccess添加和.invoke是因为我有一个将在处理串口数据进行更改,并希望NotifyCollectionChanged通过WPF数据绑定来处理集合。 (原因我不是100%肯定是因为它是几个月前,我写了一部分,它的所有工作很大的图形用户界面,现在增加了控制台应用程序,使我重新思考一些这方面的)

我想创建它们的线程上运行这些程序我的业务层,我需要这来自我的GUI版本和命令行版本的工作。

我是否滥用调度员在我的业务层?有没有更好的方式来处理从串口一个事件,然后返回到主线程来处理这些数据?

更新:

 私人代表小组NewDataRecieved(BYVAL的ByteBuffer()作为字节)
私人小组DataReceived(BYVAL的ByteBuffer()作为字节)处理_serial.DataRecieved
    如果_dispatcher.CheckAccess(),然后
        ProcessTheData
    其他
        昏暗dataReceivedDelegate作为NewDataRecieved
        dataReceivedDelegate =新NewDataRecieved(AddressOf DataReceived)
        _dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,dataReceivedDelegate,ByteBuffer的)
    结束如果
结束小组
 

解决方案

调用不会做任何事情,因为你没有一个调度运行,从调度员必须调用Dispatcher.Run(得到任何服务<一HREF =htt​​p://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.run.aspx rel="nofollow">http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.run.aspx )

现在,你的问题是,调用Dispatcher.Run将使WPF把线程的控制权 - 这可能不是你想要做一个控制台应用程序是什么

我想在您的情况最好的选择是从业务层,进入包装对象删除线程同步code(任何会谈调度程序)。

在WPF应用程序可以继续使用的包装物和控制台应用程序可以直接使用原始的经营层和以前一样工作。

更新:这里是下面的包装的一个例子,你必须创建一个方法/属性,做穿线工作,并调用原始对象的原始类的每个公共成员

 公共类BOWrapper:INotifyPropertyChanged的
{
    私人BO _bo;
    私人Dispather _dispather;

    公共BOWrapper(钵钵,调度dispather)
    {
        _bo =波;
        _dispather = dispather;
        _bo.PropertyChanged + = BOPropertyChanged;
    }

    公共字符串someValue中
    {
        {返回_bo.SomeValue; }
    }

    私人无效BOPropertyChanged(对象发件人,PropertyChangedEventArgs EA)
    {
        _dispatcher.Invoke(
            新的动作&LT; PropertyChangedEventArgs&GT;(
                E =&GT;
                {
                    VAR处理器=的PropertyChanged;
                    如果(!处理程序= NULL)处理器(这一点,E);
                }),EA);
    }
}
 

包装类是100%的样板code,你可能可以使用一些code生成器来创建它,甚至使用类似DynamicProxy(的 http://www.castleproject.org/dynamicproxy/index.html )在运行时自动生成的。

I wrote an application in WPF / VB and separated the business logic and UI into different projects.

The business layer uses a serial port which runs on a different thread, Now that I'm trying to write a command line interface for the same business layer, it seems to fail when .Invoke() is called. (no error, just doesn't work)

I'm pretty sure the reason I had to add in checkaccess and .invoke was because I have collections that would be changed during processing the serial port data and wanted the NotifyCollectionChanged to be handled by WPF data binding. (The reason I'm not 100% sure is because it was months ago I wrote that part and it all worked great from the GUI, now adding the console app has made me rethink some of this)

I would like my business layer to run these processes on the thread they were created, I need this to work from both my GUI version and the command line version.

Am I misusing the Dispatcher in my business layer? Is there a better way to handle an event from the serial port, and then return to the main thread to processes the data?

Updated:

Private Delegate Sub NewDataRecieved(ByVal byteBuffer() As Byte)
Private Sub DataReceived(ByVal byteBuffer() As Byte) Handles _serial.DataRecieved
    If _dispatcher.CheckAccess() Then
        ProcessTheData
    Else
        Dim dataReceivedDelegate As NewDataRecieved
        dataReceivedDelegate = New NewDataRecieved(AddressOf DataReceived)
        _dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal, dataReceivedDelegate, byteBuffer)
    End If
End Sub

解决方案

Invoke doesn't do anything because you don't have a dispatcher running, to get any services from a dispatcher you have to call Dispatcher.Run ( http://msdn.microsoft.com/en-us/library/system.windows.threading.dispatcher.run.aspx )

Now, your problem is that calling Dispatcher.Run will make WPF take control of the thread - and that is probably not what you want to do in a console application.

I think the best option in your situation is to remove the thread synchronization code (anything that talks to a dispatcher) from your business layer and into wrapper objects.

The WPF app can continue to work as before by using the wrapper objects and the console app can use the "raw" business layer directly.

Update: here is an example of the wrapper below, you have to create a method/property for every public member of the original class that does the threading work and calls the original object.

public class BOWrapper : INotifyPropertyChanged
{
    private BO _bo;
    private Dispather _dispather;

    public BOWrapper(BO bo, Dispatcher dispather)
    {
        _bo = bo;
        _dispather = dispather;
        _bo.PropertyChanged += BOPropertyChanged;
    }

    public string SomeValue
    {
        get { return _bo.SomeValue; }
    }

    private void BOPropertyChanged(object sender, PropertyChangedEventArgs ea)
    {
        _dispatcher.Invoke(
            new Action<PropertyChangedEventArgs>(
                e=>
                {
                    var handler = PropertyChanged;
                    if(handler!=null) handler(this,e);
                }),ea);
    }
}

The wrapper class is 100% boilerplate code and you probably can use some code generator to create it, maybe even use something like DynamicProxy ( http://www.castleproject.org/dynamicproxy/index.html ) to generate it automatically at runtime.

这篇关于Dispatcher.CheckAccess()不是从我的控制台应用程序的工作,有没有更好的办法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆