0

タスク 1 があるとします。

private void Task1()
{
    //Here is some Code, could be any "longer" Task - 
    //For Example: Grab all words from a .txt File and fill in a List<String>
}

次に、別のタスク 2 があります。

private void Task2(string word)
{
   //So lets say theres a Label on my WinForm..
   //Now While Task1 is grabbing the words, Task2 should fill a Label 
   //with the added 'word' (parameter) - (Task2 will be called from Task1
}

実際、これを可能にする方法、または最善の方法はわかりません。Label.TextUI では、変更 (すべての単語)を確認できるはずです。だから、2 番目のスレッドを作成する必要がありますか? どうすればこれを行うことができますか?誰かが私を助けてくれるかもしれません、乾杯

アップデート:

バックグラウンドワーカーで試してみましたが、何かが間違っているようです..実際には機能していません.フォームでは何も起こりません

コード:

public void CreateAndSaveAMatch(DateTime date) //That method is being called several times
{   
    //HERE IS CODE, WHICH CREATES AND SAVES A MATCH

    // Start the asynchronous operation.
    backgroundWorker1.RunWorkerAsync(date);

}

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{      
    backgroundWorker1.ReportProgress(0, Convert.ToDateTime(e.Argument).ToShortDateString());          
}

private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    label1.Text = (string)e.UserState; //here on the Label I would like to show the Date
}
4

4 に答える 4

2

はい、これを試してください。これは、を使用して問題を解決する方法を示す簡単な例ですBackgroundWorker。また、他にも多くの解決策があることに注意してください。この例を使用するには、ボタンとラベルのみを持つ新しいプロジェクトでフォームを作成します。また、これは正しかった他の回答の補足であることに注意してください。

public partial class Form1 : Form
    {
        BackgroundWorker createAndSaveAMatchBGW;
        public Form1()
        {
            InitializeComponent();
            createAndSaveAMatchBGW = new BackgroundWorker();
            createAndSaveAMatchBGW.DoWork += new DoWorkEventHandler(createAndSaveAMatchBGW_DoWork);
            createAndSaveAMatchBGW.ProgressChanged += new ProgressChangedEventHandler(createAndSaveAMatchBGW_ProgressChanged);
            createAndSaveAMatchBGW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(createAndSaveAMatchBGW_RunWorkerCompleted);
            createAndSaveAMatchBGW.WorkerReportsProgress = true;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            createAndSaveAMatchBGW.RunWorkerAsync(DateTime.Now);
        }

        void createAndSaveAMatchBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("BackgroundWorker finished");
        }

        void createAndSaveAMatchBGW_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            label1.Text = ((DateTime)e.UserState).ToString("ss");
        }

        void createAndSaveAMatchBGW_DoWork(object sender, DoWorkEventArgs e)
        {
            //BackgroundWorker does something for a 10 seconds, each second it Reports
            BackgroundWorker bgw = (BackgroundWorker)sender;
            DateTime dt = (DateTime) e.Argument;
            for (int i = 0; i < 10; i++)
            {
                Thread.Sleep(1000);
                dt = dt.AddSeconds(1);
                bgw.ReportProgress(0, dt);
            }
        }
    }

また、CreateAndSave ...メソッドからのレポートを実行ごとに1回だけ行う場合は、次のコードを使用できます。

BackgroundWorker createAndSaveAMatchBGW;
        public Form1()
        {
            InitializeComponent();
            createAndSaveAMatchBGW = new BackgroundWorker();
            createAndSaveAMatchBGW.DoWork += new DoWorkEventHandler(createAndSaveAMatchBGW_DoWork);
            createAndSaveAMatchBGW.RunWorkerCompleted += new RunWorkerCompletedEventHandler(createAndSaveAMatchBGW_RunWorkerCompleted);
        }

        private void button1_Click(object sender, EventArgs e)
        {
            createAndSaveAMatchBGW.RunWorkerAsync(DateTime.Now);
        }

        void createAndSaveAMatchBGW_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            label1.Text = ((DateTime)e.Result).ToString();
        }

        void createAndSaveAMatchBGW_DoWork(object sender, DoWorkEventArgs e)
        {
            DateTime dt = (DateTime) e.Argument;
            //you do something with your DateTime
            dt = dt.AddDays(10);
            e.Result = dt;
        }
于 2012-10-28T21:40:24.627 に答える
2

BackgroundWorker最初のタスクからの進捗状況を報告するために使用します。このコンポーネントをツールボックスからフォームにドラッグしDoWorkProgressChangedイベントを購読します。プロパティも に設定WorkerReportsProgressしますtrue。次に、最初のタスクを非同期で開始します。

// this will execute code in `DoWork` event handler
backgroundWorker1.RunWorkerAsync();

次へ -userStateオブジェクトを使用して、処理された単語を渡します。

private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{      
    // grab words in a loop and report progress
    backgroundWorker1.ReportProgress(0, word);
}

そして最後のステップ -ProgressChangedイベント ハンドラーでラベルを更新する

void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    label1.Text += (string)e.UserState; // this is your grabbed word
}
于 2012-10-28T20:13:44.200 に答える
1

このようなことを実現する最も簡単な方法は、BackgroundWorker を使用することです。

http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

BackgroundWorker は、スレッドのマーシャリングを自動的に処理し、UI を更新できるイベントを提供します。イベント ハンドラーは UI スレッドで実行されます。

Task1 で行うことは BackgroundWorker に移動することができ、Task2 で行うことを提案する UI の更新は、実際には BackgroundWorker からの進行状況イベントに応答することができます。

ProgressChangedEventArgsは、現在の単語を保持できるユーザー定義データを提供します。

ただし、ロードするすべての単語を表示する場合、Winforms (および実際にはほとんどすべての UI) は、ファイルから単語をロードするだけの別の CPU スレッドに追いつくことができません。

于 2012-10-28T20:14:02.637 に答える
0

Task1別のスレッドで開始できます。

Task2TextBox を更新するために実行される複雑なロジックがない限り、実際には必要ありません。あなたが本当にする必要があるのはTextBox.Invoke()、 から UI スレッドで更新を呼び出すために使用することTask1です。

于 2012-10-28T20:13:01.077 に答える