0

mainBwUI (WPF) スレッドでBackgroundWorker () を作成しました。1.5秒間スリープしApplication.Current.Dispatcher.Invoke、「グローバル」text変数からTextBoxにテキストを出力するだけの関数を呼び出す無限ループがあります。

また、ループの前に、別の ( child) ReportsProgress を作成する BackgroundWorker を作成し、ProgressChanged イベント ハンドラーでtext変数を変更します。

mainBwループ内にWinFormsの Application.DoEvents() みたいなものがなくてイベントハンドラを処理できないのでうまくいかないと思っていました。しかし、それは機能します。なんで?

コードは次のとおりです。

using System;
using System.ComponentModel;
using System.Threading;
using System.Windows;

namespace WpfApplication6
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        private BackgroundWorker mainBw = new BackgroundWorker();

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            mainBw.DoWork += MainBwOnDoWork;

            mainBw.RunWorkerAsync();

            btn.IsEnabled = false;
        }

        private string text = "abc";

        private void MainBwOnDoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();

            bw.DoWork += BwOnDoWork;
            bw.ProgressChanged += BwOnProgressChanged;
            bw.WorkerReportsProgress = true;

            bw.RunWorkerAsync();

            while (true)
            {
                Thread.Sleep(1500);

                text += " main ";

                Application.Current.Dispatcher.Invoke(new Action(() => { WriteToUIThread(); }));
            }
        }

        private void WriteToUIThread()
        {
            tbox.Text = DateTime.Now + " " + text + Environment.NewLine + tbox.Text;
        }

        private void BwOnProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            text += e.UserState.ToString();
        }

        private void BwOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
        {
            while (true)
            {
                Thread.Sleep(3000);

                (sender as BackgroundWorker).ReportProgress(0, "child");
            }

        }
    }
}

    // XAML
<Window x:Class="WpfApplication6.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Button Name="btn" Content="Button" HorizontalAlignment="Left" Height="105" Margin="43,47,0,0" VerticalAlignment="Top" Width="165" Click="Button_Click"/>
        <TextBox Name="tbox" HorizontalAlignment="Left" Height="114" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="456" Margin="27,182,0,0"/>
    </Grid>
</Window>
4

3 に答える 3

1

BackgroundWorkerがバックグラウンド スレッドで動作するため、動作します (名前の由来)。UIスレッドで実行されていないため、UIスレッドをブロックしていません。UIスレッドで実行される短いメソッドを時々送信しているだけです。

とはいえ、問題を解決するための特に適切に設計されたアプローチではありません。3 秒ごとにコードを実行したい場合は、Timer代わりに a を使用してください。名前空間でタイマーを使用するFormsと、代わりに UI スレッドでイベントが発生します。

于 2013-10-21T16:11:16.253 に答える
0

これが機能するのは、BackgroundWorkerその名前が示すように、メイン UI スレッドとは独立してバックグラウンド スレッドで実行されるためです。

-eventは UI スレッドにマーシャリングされるため、関連するコントロールで -methodsReportProgressを呼び出すことなく、このイベントを簡単に処理できます。Invoke

逆に、WinForms の-method を使用すると、プロセスはバックグラウンド スレッドを使用せずApplication.DoEvents()に、メイン スレッドで長時間実行される操作を実行するために他のメッセージを処理できました。

于 2013-10-21T16:11:34.600 に答える