当我将浏览器控件传递给跟踪浏览器控件值的后台任务时,我收到此错误。我需要在代码中进行哪些更改,以便将此浏览器控件安全地传递给我的后台刮刀类。
错误
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);
});
}
}
答案 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);
这避免了总是必须在同步上下文之间来回切换的相当大的成本