0

これは、デリゲート、イベント、バックグラウンドワーカー、WPF の使用への私の最初の進出です...ほとんどすべてが新しいものです。進行状況を報告したい長期実行メソッドを実行する外部クラスがあります。

public class ShortFileCreator
{
    public void CreateShortUrlFile(string outputfilepath)
    {         
        foreach(string line in lines)
        {
                //work work work processing file
                if (ReportProgress != null)
                {
                //report progress that a file has been processed
                    ReportProgress(this, new ProgressArgs {TotalProcessed = numberofurlsprocessed
                                                         , TotalRecords = _bitlyFile.NumberOfRecords});
                }
        }
    }

    public delegate void ReportProgressEventHandler (object sender, ProgressArgs args);

    public event ReportProgressEventHandler ReportProgress;

    public class ProgressArgs : EventArgs
    {
        public int TotalProcessed { get; set; }
        public int TotalRecords { get; set; }
    }
}

私の WPF フォームで、CreateShortUrlFile メソッドを開始し、フォームのプログレス バーを更新したいと考えています。

private void btnRun_Click(object sender, RoutedEventArgs e)
    {
       var shortFileCreator = new ShortFileCreator();           

        _worker = new BackgroundWorker
        {
            WorkerReportsProgress = true,
            WorkerSupportsCancellation = true
        };

        shortFileCreator.ReportProgress += ShortFileCreator_ReportProgress;

        _worker.DoWork += delegate(object s, DoWorkEventArgs args)
        {
            _bitlyFileWorker.CreateShortUrlFile(saveFileDialog.FileName);
        };

        _worker.RunWorkerAsync();
    }

    protected void ShortFileCreator_ReportProgress(object sender, ShortFileCreator.ProgressArgs e)
    {
        //update progress bar label
        txtProgress.Content = String.Format("{0} of {1} Records Processed", e.TotalProcessed, e.TotalRecords);
        //update progress bar value
        progress.Value = (double) e.TotalProcessed/e.TotalRecords;
    }

ただし、これを実行すると、1行が処理され、例外が発生します。別のスレッドが所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。これを所有している他のスレッドは何ですか?ReportProgress イベントは、サブスクライバーに ProgressArgs を返すべきではありませんか?

4

1 に答える 1

1

これは、ProgressBarやのような UI コントロールTextBoxが別のスレッドで操作できないためです。この場合、BackgroundWorkerスレッドからそれらを更新しようとしています。

これを回避するInvokeには、UI スレッドにコールバックします。Dispatcher

protected void ShortFileCreator_ReportProgress(object sender, ShortFileCreator.ProgressArgs e)
{
    Dispatcher.Invoke((Action)delegate
    {
       //update progress bar label
       txtProgress.Content = String.Format("{0} of {1} Records Processed", e.TotalProcessed, e.TotalRecords);
       //update progress bar value
       progress.Value = (double) e.TotalProcessed/e.TotalRecords;
    });
}
于 2013-10-17T03:12:12.920 に答える