C# 不同的线程在WPF中拥有它

C# 不同的线程在WPF中拥有它,c#,.net,wpf,multithreading,dispatcher,C#,.net,Wpf,Multithreading,Dispatcher,这是我正在使用的UserControl this.cardename.Content是一个标签,位于用户控件的UI中 public partial class PersonCredential : UserControl { public PersonCredential() { InitializeComponent(); Dispatcher.BeginInvok

这是我正在使用的
UserControl

this.cardename.Content是一个
标签,位于用户控件的UI中

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

调度器的使用方式是否有问题?
}

编辑: 我正在内容控件中实例化该用户控件,其背后的代码是:

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

编辑@DanPuzey的评论<代码>开始监视
已在另一个线程上监视。关键是没有从UI线程引发
cardarived
事件:

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或更高版本,请使用而不是
new Thread()

如果
IsReaderArrived
检查是一个即时非阻塞调用(即完成不到50毫秒),我建议使用
Task.Delay(interval)
在调用方线程上启动轮询循环:


这是一个异步循环。如果从UI线程调用
StartMonitoring
,则将在同一UI线程上触发
CardArrived
事件,并且代码的客户端不必担心
Dispatcher.BeginInvoke
。如果您需要解释这是如何发生的,read

是否从后台线程调用构造函数?这本身就是一个问题。您应该在UI线程上创建所有UI内容(包括UserControl)。请发布从何处实例化此UserControl的代码。
CheckAccess()
的结果可能会很有趣。@nowhewhomustnotbenamed我刚刚更新了我的答案以包含一个解释,@DanPuzey在注释中比我更清楚。事件是从另一个线程引发的-您在
StartMonitoring
@中启动的线程现在他不应该被命名,我在中解释了这一点。非常感谢。如果您能告诉我为什么没有新线程的调度程序不能工作,但
线程下的同一任务运行良好,那将非常有帮助。我认为不需要
新线程(…).Start()
——此解决方案的重要部分是事件处理程序中的
调度程序.Invoke
。通常不会从dispatcher线程调用事件处理程序,这可能是错误的来源。@DanPuzey是的,但
StartMonitoring
以无限循环等待,请参阅question@DanPuzey:是的,你是对的。刚刚删除了
新线程(…).Start()
并且一切都是一样的:)如果
StartMonitoring()
在无限循环中等待,那么事件处理程序将永远不会被设置(代码将在到达
type.CardArrived+=…
之前在无限循环中阻塞)-所以我认为你的说法不太正确。现在我明白了。非常感谢<代码>调度程序
现在似乎没有必要!
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);
    }
}