私は、RevitというアーキテクチャモデリングソフトウェアのAPIを使用してカスタムアドインコマンドを作成しています。私のコマンドは完了するまでに時間がかかることがあるので、進行中のバーが表示された状態でユーザーにウィンドウを表示したい。別のスレッドでWPF進捗ウィンドウを作成
通常、このようなプログレスウィンドウを作成する場合は、メインUIスレッド上にあり、実行される実際の作業はセカンダリワーカースレッドで行われます。ただし、Revitでは、カスタムコマンドを呼び出すスレッドを介してAPIにアクセスする必要があります。だから私は2番目のスレッドで進捗バーを作成する必要があります。
このブログの投稿はlaunching a WPF window in a separate threadで、私の解決策に基づいています。ここに私のカスタムコマンドクラスがあります。
public class SampleProgressWindowCommand : Autodesk.Revit.UI.IExternalCommand
{
private ProgressWindow progWindow;
internal static EventWaitHandle _progressWindowWaitHandle;
public Result Execute(ExternalCommandData commandData, ref string message, ElementSet elements)
{
//Starts New Progress Window Thread
using (_progressWindowWaitHandle = new AutoResetEvent(false))
{
//Starts the progress window thread
Thread newprogWindowThread = new Thread(new ThreadStart(ShowProgWindow));
newprogWindowThread.SetApartmentState(ApartmentState.STA);
newprogWindowThread.IsBackground = true;
newprogWindowThread.Start();
//Wait for thread to notify that it has created the window
_progressWindowWaitHandle.WaitOne();
}
//Does some work that takes a long time
for (int i = 1; i <= 100; i++)
{
//Updates Progress
this.progWindow.UpdateProgress("Item " + i.ToString(), i, 100);
//Does some fake work
System.Threading.Thread.Sleep(700);
}
//closes the Progress window
progWindow.Dispatcher.Invoke(new Action(progWindow.Close));
//Show Result to User
Autodesk.Revit.UI.TaskDialog.Show("Task", "Task Completed");
return Result.Succeeded;
}
private void ShowProgWindow()
{
//creates and shows the progress window
progWindow = new ProgressWindow();
progWindow.Show();
//makes sure dispatcher is shut down when the window is closed
progWindow.Closed +=new EventHandler(progWindow_Closed);
//Notifies command thread the window has been created
_progressWindowWaitHandle.Set();
//Starts window dispatcher
System.Windows.Threading.Dispatcher.Run();
}
}
そして、ここでは私のProgressWindowクラス上のUpdateProgress()メソッドは
あるpublic void UpdateProgress(string message, int current, int total)
{
this.Dispatcher.Invoke(new Action<string, int, int>(
delegate(string m, int v, int t)
{
this.progressBar1.Maximum = System.Convert.ToDouble(t);
this.progressBar1.Value = System.Convert.ToDouble(v);
this.messageLbl.Content = m;
}),
System.Windows.Threading.DispatcherPriority.Background,
message, current, total);
}
私の最初の質問は、一般的にある私はこの権利をしましたか?それはうまくいくように思えますが、今日は機能しているということを知るためにマルチスレッドプログラミングについて十分に知っていますが、明日は動作するとは限りません。
第2に、進行状況ウィンドウにキャンセルボタンを追加して、プロセスをキャンセルできるようにしたいと思います。これを行う最善の方法は何ですか?私は最終的に、作業スレッドによって定期的にチェックされる "cancelRequested"ブールフラグに終わることを理解していますが、これを進捗ウィンドウのスレッドからどのように設定するのですか?
1 - AutoDeskで作業していますか?本当に? 2 - 適切なViewModelを作成し、ViewModelで2次ディスパッチャ・スレッドのプロパティ変更を発生させます。 –
RevitはAutodeskによって作成されましたが、Autodeskではうまくいきません。通常、私が行うWPFはすべてMVVMですが、この例では簡単にするため、 '進行状況フォームのViewModelクラスを作成しませんでした。 –
@EricAnastas私はこのスレッドが少し古いことを知っていますが、私は新しいと私の質問は非常にこの課題に近い見つけることができませんでした。外部イベントを開始したGUIを更新する方法はありますか? – Thibaud