6

私のwpf(c#)アプリケーションでは、ユーザーがボタンを押すと長いプロセスが実行されます。完全なコードが実行されるまでボタンを押すと、ウィンドウがフリーズし、ユーザーはウィンドウ内の他のタスクを実行できなくなります。ウィンドウがユーザーに反応するように、バックグラウンドプロセスとしてボタンクリックコードを作成するにはどうすればよいですか。次の方法を試しましたが、失敗しました。

private void btn_convert_Click(object sender, RoutedEventArgs e)
{
    Dispatcher.CurrentDispatcher.BeginInvoke(DispatcherPriority.Background, 
    new Action(() => { 

         WorkerMethod();
    }));
}

ここで、WorkerMethodは、コード全体を含む関数です。提案。

よろしく、
Sangeetha

4

6 に答える 6

12

.NET 4.5 をターゲットにしている場合はasync/await、UI をレスポンシブにするために使用できます。

private async void btn_convert_Click(object sender, RoutedEventArgs e)
{
    await WorkerMethod();
}

あなたの変更WorkerMethod

private Task WorkerMethod()
{
    return Task.Run(() =>
        {
           // your long running task here
        });
}
于 2013-03-14T12:53:24.997 に答える
7

ここでの回答に代わるものは、BackgroundWorker です。完了後に GUI スレッドに戻るという追加の利点があります。

private void btn_convert_Click(object sender, RoutedEventArgs e)
{
    BackgroundWorker worker = new BackgroundWorker();
    worker.DoWork += WorkerMethod;
    worker.RunWorkerCompleted += WorkerEnded;
    worker.RunWorkerAsync();
}

private void WorkerMethod()
{
    // New thread, cannot access GUI
}

private void WorkerEnded()
{
    // Back on the GUI Thread
    // Worker is finished
}
于 2013-03-14T12:43:04.817 に答える
7

ここで実際に行ったことは、Dispatcher を介して負荷の高いタスクを実行するよう UI スレッドに要求することです。

新しいスレッド/タスクを作成し、バックグラウンド メソッドを実行させる必要があります。

Thread t = new Thread(() => WorkerMethod());
t.Start();

詳細については、これを読んでください:

WPF BackgroundWorker と Dispatcher の比較

WPFの「ディスパッチャー」を理解する

于 2013-03-14T12:40:46.173 に答える
1

でメソッドを呼び出していますUI-Dispatcher。これにより、UI がフリーズします。を使用してクリックイベントに新しいスレッドを作成します

private void btn_convert_Click(object sender, RoutedEventArgs e)
    {
         Thread t = new Thread(new ThreadStart(WorkerMethod));
         //assign STA or MTA, etc....
         t.Start();
    }

「System.Threading.Thread」についてはこちらをご覧ください。

于 2013-03-14T12:40:28.630 に答える
1

私が非常に誇りに思っている別の方法を想像しました: マルチスレッドがIHMがプログレスバーをアニメーション化できるようにするだけの場合、ユーザーがプロセスを確認しているihmと対話することを想定されていない場合、または単に開発する時間がない場合マルチスレッドであり、フィードバックなしでアプリケーションをフリーズさせることはできません:

別のウィンドウを作成し、フリーズしたウィンドウの中央にこのローダーを表示する別の STA スレッドで起動されるローダーを開発できます。

これは、私が記事を作成した投稿とそのようなソリューションの実装です。

http://charly-studio.com/blog/a-loader-for-wpf-long-ui-process/

コンポーネントの使用方法は次のとおりです。

private void MainWindow_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    // Long UI process context
    using (new LongUIProcessContext("Wait while loading..."))
    {
        Thread.Sleep(2000);

        // Sub long ui process context
        using (new LongUIProcessContext("Wait while loading 2..."))
        {
            Thread.Sleep(2000);
        } 

        // Another sub long ui process context
        using (new LongUIProcessContext("Wait while loading 3..."))
        {
            Thread.Sleep(2000);
        }
    }
}

そして、私が提案するベンチは次のようになります。 長い Ui プロセス ベンチ

そして、これがコンポーネントを見つけることができる私が作ったベンチの直接リンクです:

ベンチ ソリューションの直接ダウンロード

于 2013-09-06T13:40:21.727 に答える
0

Backgroundworker クラスを使用してみてください。DoWork イベントに登録し、すべての処理コードを配置するイベント ハンドラーを作成する必要があります。RunWorkerAsync メソッドを使用してワーカーを開始します。ワーカーの進捗状況を報告できるメソッド「ReportProgress」もあります。RunWorkerCompleted は、ワーカーがコードの処理を完了すると表示されます。BackgroundWorker の後にインターネットで検索してみてください。使用方法の例がたくさん見つかります。

于 2013-03-14T12:45:18.180 に答える