1

ブラウザ コントロールの値を追跡するバックグラウンド タスクにブラウザ コントロールを渡すときに、このエラーが発生します。このブラウザー コントロールをバックグラウンド スクレーパー クラスに安全に渡すには、コードにどのような変更が必要ですか。

エラー

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);
           });
        }
    }
4

2 に答える 2

2

STA スレッドを実行しているタスクを開始する必要があります。

そのためには、TaskScheduler.FromCurrentSynchronizationContextを使用する必要があります (タスクの作成元のスレッド自体が STA スレッドであると仮定します)。

これは、TaskScheduler 引数を受け入れるTaskFactory.StartNewのオーバーロードの 1 つに渡すことができます。

例えば:

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

また、 FromCurrentSynchronizationContext STAをグーグルで検索することをお勧めします。

于 2013-03-17T23:08:17.353 に答える
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);

これにより、同期コンテキスト間を常に切り替えなければならないというかなり大きなコストが回避されます。

于 2013-03-17T23:19:26.547 に答える