1

メールを作成して送信するためのBackgroundWorkerスレッドを生成するボタンのあるWPFウィンドウがあります。このBackgroundWorkerの実行中に、メッセージの後にアニメーション化された「...」を表示するユーザーコントロールを表示したいと思います。そのアニメーションは、ユーザーコントロール内のタイマーによって実行されます。

私のメール送信コードはBackgroundWorkerにありますが、ユーザーコントロールのタイマーは呼び出されません(そうですが、Backgroundworkerが終了したときにのみ呼び出されます。これは、目的に反します...)。

WPFウィンドウの関連コード:

private void button_Send_Click(object sender, RoutedEventArgs e)
{
    busyLabel.Show(); // this should start the animation timer inside the user control

    BackgroundWorker worker = new BackgroundWorker();
    worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
    worker.DoWork += new DoWorkEventHandler(worker_DoWork);
    worker.RunWorkerAsync();      
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    this.Dispatcher.Invoke((Action)(() =>
    {      
        string body = textBox_Details.Text;
        body += "User-added addtional information:" + textBox_AdditionalInfo.Text; 

        var smtp = new SmtpClient
        {
            ...
        };

        using (var message = new MailMessage(fromAddress, toAddress)
        {
            Subject = subject,
            Body = body
        })
        {
            smtp.Send(message);
        }
    }));

}

ユーザーコントロールの関連コード( "BusyLabel"):

public void Show()
{
    tb_Message.Text = Message;
    mTimer = new System.Timers.Timer();
    mTimer.Interval = Interval;
    mTimer.Elapsed += new ElapsedEventHandler(mTimer_Elapsed);
    mTimer.Start();
}

void mTimer_Elapsed(object sender, ElapsedEventArgs e)
{
    this.Dispatcher.Invoke((Action)(() =>
    { 

        int numPeriods = tb_Message.Text.Count(f => f == '.');
        if (numPeriods >= NumPeriods)
        {
            tb_Message.Text = Message;
        }
        else
        {
            tb_Message.Text += '.';
        }         
    }));
}

public void Hide()
{
    mTimer.Stop();
}

なぜそれがロックアップしているのか、何か考えはありますか?

4

1 に答える 1

2

メソッドでを使用Dispatcher.Invokeするworker_DoWorkと、実行が UI スレッドに戻されるため、実際には非同期で作業を行っているわけではありません。

表示しているコードに基づいて、それを削除できるはずです。

作業が完了した後に表示する必要がある結果値がある場合は、それを に配置すると、ハンドラーのイベント引数DoWorkEventArgsで (UI スレッドで) アクセスできるようになります。worker_RunWorkerCompleted

を使用する主な理由BackgroundWorkerは、マーシャリングが内部で処理されるため、使用する必要がないためですDispatcher.Invoke

于 2013-01-15T21:22:34.717 に答える