WPF中的多线程编程

时间:2013-03-17 22:45:20

标签: c# wpf .net-4.5

当我将浏览器控件传递给跟踪浏览器控件值的后台任务时,我收到此错误。我需要在代码中进行哪些更改,以便将此浏览器控件安全地传递给我的后台刮刀类。

错误

The calling thread must be STA, because many UI components require this.

以下是我将浏览器控件传递给后台单例类的方法。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            brwser.Navigate("https://xyz.com");
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            Task.Factory.StartNew(() =>
           {
               if (BfScrapper.Instance.CanStart)
                   BfScrapper.Instance.StartTask(brwser);
           });
        }
    }

2 个答案:

答案 0 :(得分:2)

您必须启动正在运行STA线程的任务。

为此,您需要使用TaskScheduler.FromCurrentSynchronizationContext(假设您创建任务的线程本身就是STA线程)。

您可以将此传递给接受TaskScheduler参数的TaskFactory.StartNew重载之一。

例如:

Task.Factory.StartNew
(
    () =>
    {
        if (BfScrapper.Instance.CanStart)
            BfScrapper.Instance.StartTask(brwser);
    },
    CancellationToken.None,
    TaskCreationOptions.None,
    TaskScheduler.FromCurrentSynchronizationContext()
);

我还建议您使用google FromCurrentSynchronizationContext STA ,因为这些内容远非明显,并且有分歧。

答案 1 :(得分:1)

我猜你试图在传递的UI元素中改变一些东西。最简单的方法是:

UIElement.Dispatcher.BeginInvoke(/*do stuff here*/);

我有一个方便的扩展方法:

public static DispatcherOperation DispatcherCall<T>(this T obj, Action action, DispatcherPriority priority) where T : DispatcherObject
        {
            return obj.Dispatcher.BeginInvoke(priority, action);
        }

用法如下:

mLabel.DispatcherCall(() => mLabel.Text = "Test...", DispatcherPriority.Normal);

这避免了总是必须在同步上下文之间来回切换的相当大的成本