0

だから私は最初のマルチスレッド WPF アプリに取り組んでいます。私はマルチスレッドを実装する方法をほとんど、またはまったく理解していないことを覚えておいてください - 私はいくつかのアプリでそれを行い、常に既存のコードから作業しています. これは、明らかにWindowsフォームとはまったく異なるWPFでの私の最初の試みです...

したがって、基本的に私はこの例に取り組んでいますが、奇妙なことに、新しいスレッドをインスタンス化して開始する必要があることについて言及していません-著者は、私のような初心者にとっても自明であると感じたと思います.

InvalidOperationExceptionいずれにせよ、UI コントロールのプロパティを更新したいポイントに到達するまで問題なく動作します。別のスレッド

したがって、基本的にこれはスレッドセーフな方法ではありませんが、これをどのように修正すればよいか途方に暮れています...

これが私のコードです:

string fn = "";

private void btnBrowse_Click(object sender, RoutedEventArgs e)
{
    if (lblActivity.Visibility != System.Windows.Visibility.Hidden)
    {
        lblActivity.Visibility = System.Windows.Visibility.Hidden;
    }
    if (lstResult.Items.Count != 0)
    {
        lstResult.Items.Clear();
    }

    OpenFileDialog ofd = new OpenFileDialog();

    Nullable<bool> result = ofd.ShowDialog();

    if (result == true)
    {
        txtSource.Text = ofd.FileName;
        txtDest.Text = ofd.FileName;
        fn = ofd.SafeFileName;

        PopulateControlsDuingLongRefreshCall("read");
    }
}

private void PopulateControlsDuingLongRefreshCall(string action)
{
    ShowProcessing();

    ThreadStart ts = delegate
    {
        switch (action)
        {
            case "format":
                Populate();
                CleanData();
                break;
            case "read":
                TextReader tr = new StreamReader(txtSource.Text);
                txtPreview.Text = tr.ReadToEnd();
                break;
        }

        Dispatcher.BeginInvoke(DispatcherPriority.Normal, (EventHandler)delegate
        {
            HideProcessing();
        }, null, null);

    };
    Thread thr = new Thread(ts);
    thr.Start();
}

private void ShowProcessing()
{
    recProcessing.Visibility = Visibility.Visible;
}
private void HideProcessing()
{
    recProcessing.Visibility = Visibility.Collapsed;
}

誰かがここで解決策を提案したり、私が使用している概念について詳しく説明したり (私はまだかなりあいまいです) して、自分で解決策を見つけるのに十分な理解を得ることができれば、それは大歓迎です.

前もって感謝します!

編集
UIコントロールのプロパティを取得している場合もエラーが発生しTextReader tr = new StreamReader(txtSource.Text);、例外がスローされます。

4

2 に答える 2

1

デリゲートでは、txtSourceに直接アクセスするのではなく、次の関数を使用してストリームリーダーを返します。

    private StreamReader GetTxtSource()
    {
        if (!this.Dispatcher.CheckAccess())
        {
            return this.Dispatcher.Invoke(new Func<StreamReader>(this.GetTxtSource)) as StreamReader;                
        }
        return new StreamReader(txtSource.Text);
    }

代わりにtxtSource.Dispatcher.CheckAccess()を使用する必要がある場合があります。

于 2013-02-08T13:06:33.453 に答える
0

ここで本当に理解しておく必要があるのは、UI スレッド以外のスレッドからはコントロールにアクセスできないということです。

だから、あなたがやっているとき

 case "read":
            TextReader tr = new StreamReader(txtSource.Text);
            txtPreview.Text = tr.ReadToEnd();
            break;

バックグラウンド スレッドで Textbox (txtPreview) の値を設定しようとしています。

必要なことは、バックグラウンド スレッドでファイルの内容を読み取り、UI スレッドを使用して、Dispatcher を使用してテキスト ボックスの値を更新することです。

 case "read":
            TextReader tr = new StreamReader(txtSource.Text);
            string content = tr.ReadToEnd();

            Dispatcher.Invoke((Action)(() =>
            {
                txtPreview.Text = content;
            }));
            txtPreview.Text = tr.ReadToEnd();
            break;
于 2013-02-08T16:25:12.920 に答える