不同的线程在WPF中拥有它

时间:2014-02-10 13:49:24

标签: c# .net wpf multithreading dispatcher

这是我正在使用的UserControl

this.CardHolderName.Content是用户控件的UI中的label

public partial class PersonCredential : UserControl
        {
            public PersonCredential()
            {
                InitializeComponent();

                Dispatcher.BeginInvoke( (Action) (() => {
                        SCLib type = new SCLib();
                        type.StartMonitoring();

                        type.CardArrived += (string ATR) => { this.CardHolderName.Content = ATR; };
                    };
               }));

我仍然收到错误,“ 调用线程无法访问此对象,因为其他线程拥有它 ”,即使我使用的是Dispatcher.BeginInvoke

使用Dispatcher的方式有问题吗?                 }

编辑: 我在内容控件中实例化用户控件,代码隐藏是:

public partial class MainWindow : Window
    {
       PersonCredential personCredential {get;set;}

        public MainWindow()
        {

            InitializeComponent();
            var personCredential = new CoffeeShop.PersonCredential();
            //create an instance of user control.
            this.personCredentials.Content = personCredential;
            // assign it to the content control inside the wpf main window
            .. // blah blah
        } 

编辑1:

启动监控代码:

public async void StartMonitoring()
        {

            // Wait for user to press a key

            try
            {
                this.establishContext();

                await Task.Run(new Action(WaitForReaderArrival));
                ////WaitForReaderArrival();

                if (IsReaderArrived())

2 个答案:

答案 0 :(得分:4)

来自@ DanPuzey的评论

编辑StartMonitoring已经监视另一个线程。关键是没有从UI线程中引发CardArrived事件:

public PersonCredential()
{
    InitializeComponent();

    SCLib type = new SCLib();
    type.StartMonitoring();

    type.CardArrived += (string ATR) => { 
        // when card arrives, dispatch back to UI thread
        Dispatcher.BeginInvoke(new Action(() => {
            this.CardHolderName.Content = ATR; 
        }));
    };
}

如果您使用的是.NET 4或更高版本,请使用Task.Factory.StartNew()代替new Thread()

答案 1 :(得分:1)

如果IsReaderArrived检查是即时非阻塞调用(即完成时间不到50毫秒),我建议使用{{1}在调用者的线程上启动轮询循环}:

Task.Delay(interval)

这是一个异步循环。如果从UI线程调用public async Task StartMonitoring(int interval, CancellationToken token) { this.establishContext(); while (true) { token.ThrowIfCancellationRequested(); if (IsReaderArrived()) { // make sure to reset the flag inside IsReaderArrived // so the event won't be fired upon the next iteration if (this.CardArrived != null) this.CardArrived(this, EventArgs.Empty); } await Task.Delay(interval); } } ,则StartMonitoring事件将在同一UI线程上触发,代码的客户端将不必担心CardArrived。如果您需要解释如何发生这种情况,请阅读"It's All About the SynchronizationContext."