1

Indeterminate="True"時間のかかるタスクを実行するときに、進行状況バーを含む単純な WPF ウィンドウを表示したいと思います。

私は、Reed Copsey によるこの例に従ってソリューションを実装しました。

プロセスが完了したら、ウィンドウを閉じる必要があります。私の推測では、これを達成するには、スレッドを強制終了するか、ビュー (ウィンドウ) を閉じる必要があります。

残念ながら、どちらの方法でも次のエラーが発生します。

Abort()1)スレッドの呼び出し:

ウィンドウは閉じていますが、これは正しいのですが、まだ次のエラーが表示されます。

コードが最適化されているか、ネイティブ フレームがコール スタックの最上位にあるため、式を評価できません

2) View.Close():

別のスレッドがこのオブジェクトを所有しているため、呼び出し元のスレッドはこのオブジェクトにアクセスできません。

必要なロジックをStopThread()メソッドに実装する必要があります。ウィンドウをエレガントに閉じるために何ができるか考えてみてください。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.Threading;
using Microsoft.Practices.Composite.Presentation.Commands;

namespace ProgressBar
{
    public class ProgressBarViewModel
    {
        public DelegateCommand<object> CloseCommand { get; set; }
        Thread newWindowThread;

        string _closeButton;
        public string CloseButton 
        {
            get { return _closeButton; }
            set { _closeButton = value; }
        }

        ProgressBarView _view;
        public ProgressBarView View
        {
            get { return _view; }
            set { _view = value; }
        }

        public ProgressBarViewModel(ProgressBarView view)
        {
                CloseButton = "Close";
                CloseCommand = new DelegateCommand<object>(CloseForm);

                View = view;
                View.Closing +=new System.ComponentModel.CancelEventHandler(View_Closing);
                View.DataContext = this;
        }

        public void View_Closing(object sender,CancelEventArgs e)
        {
            StopThread();
        }

        public void CloseForm(object p)
        {
            StopThread();
        }

        private void StopThread()
        {
            try
            {
                //View.Close();
                newWindowThread.Abort();
            }
            catch (Exception eX)
            {
                Debugger.Break();
                //Getting an error when attempting to end the thread:
                //Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack
            }
        }

        public void ShowProgress()
        {
                newWindowThread = new Thread(new ThreadStart(() =>
                {
                    ProgressBarView tempWindow = new ProgressBarView();
                    tempWindow.DataContext = this;
                    tempWindow.Show();
                    System.Windows.Threading.Dispatcher.Run();
                }));

                newWindowThread.SetApartmentState(ApartmentState.STA);
                newWindowThread.IsBackground = true;
                newWindowThread.Start();
        }
    }
}
4

2 に答える 2

0

あなたがすべきことは、操作を独自のクラス内にカプセル化し、完了したとき (またはビューを閉じたいとき) にイベントを発生させることです。

イベント ハンドラーは、ビューと同じスレッドでDispatcherを実行するために を使用する必要があります。close()

于 2012-10-18T11:03:34.980 に答える
0

この操作に BackgroundWorker を使用することを検討する必要がありますか? RunWorkerCompleted イベントに応答して、ビューを閉じることができます。

public void YourFunction(Dispatcher dispatcher)
{
    BackgroundWorker bw = new BackgroundWorker();
    bw.DoWork += (sender, args) =>
      {
         ...do your long running operation
      };

    bw.RunWorkerCompleted += (sender, args) =>
      { 
         dispatcher.BeginInvoke(...close your view here);
      }

    bw.RunWorkerAsync();
}
于 2012-10-18T11:11:26.820 に答える