質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.06%

WPF,別スレッド(Task.Run)で重たい処理をしながらそれに同期してモードレスウインドウを開いたり閉じたりしたい

解決済

回答 3

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 351

score 258

WPFで時間軸に沿ってユーザにウインドウを表示したいと思いこんなソースを書いたのですがうまく動きません.
こういったことをやりたい場合どのようにするのが良いのでしょうか.
よろしくお願いいたします.

Task.Runにこだわっているわけではありません.私の知識ではこれを使うくらいしかひねり出せなかったためTask.Runを使用しています.

やりたいこと

Startボタンを押すと,
MyWindow1が開く

1秒後にMyWindow1が閉じる
※MyWindow1は自分で追加した新しいウインドウです.

X秒後にMyWindow2が開く…

Y秒後にMyWindow2が閉じる…
以下繰返しMyWindow[N]まで続く… ※下記ソースにはMyWindow1しか書いていません
実際には,MyWindowが開いている裏でシリアル通信をしたり...メインウインドウのGUIを更新したり,,,したい

どうなるか

MyWindowが開かない
Task.Runの外(前)でshowすればもちろん開く

private Button_Start_Click(object sender, RoutedEventArgs e){
  var sw = new StopWatch();    //時間計測
  sw.start();
  bool flag = true;

  Task.Run(()=>{
    while(true){
      var mw = new MyWindow();
      Dispatcher.BeginInvoke((Action)(() =>{
        mw.show();       //mwが表示されない
      }));
      if(sw.ElapsedMilliseconds > 1000 && flag){    //1000ms後に閉じてほしい
        Dispatcher.BeginInvoke((Action)(() =>{
          mw.close();    //そもそも表示してないので意味がない
        }));
        flag = false;
      }
    }
  });
}
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • dodox86

    2020/01/20 15:11

    ご質問は技術的には「UIスレッドとは別のスレッドからN個のウィンドウを時系列に沿ってShow()〜Close()したい」とのことで、それはそれで回答の価値はあると思いますが、そもそもアプリケーションとして、N個の別のウィンドウをシーケンシャルにShow()〜Close()する必要があるのでしょうか。例えば1個の状態表示用のウィンドウを生き続けさせて、表示したり、隠したり、情報更新するのではダメなのでしょうか。(そうだとしても別スレッドからウィンドウを操作するための注意点は残りますが)

    キャンセル

  • ElecDove

    2020/01/21 11:06

    質問として投稿する都合上N個という風に表現いたしましたが,実際にはいろいろな内容のウインドウを使用するため,一つのウインドウを生き残らせることは難しい案件でした
    共通部分が多いウインドウについては表示したり隠したりを使用しております

    キャンセル

回答 3

check解決した方法

0

うまく動かない原因はどうやら別の場所にあったようで,結局は上述の様なコードで動きました
その過程でhihijijiさんの提示されたソースも使用し,同じようにうまく動くことを確認しました

センサからの時系列データを扱いながら時間経過によって動作を変える処理をしたいため,結局は最初のTask.Runを使ったソースに今は落ち着いています.

※根本的な原因がどこにあったのかよくわかりません…
なぜかわからないけど動かなかったのが動くようになった,みたいな状態になってしまっています.
どうやらSerialPort関連が怪しいです.

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

こんなのでしょうか?

private async void button_Click(object sender, RoutedEventArgs e)
{
    for (int i = 0; i < 10; i++)
    {
        var window = new SubWindow { Title = $"SubWindow{i}" };
        await Task.Run(() => Dispatcher.Invoke(window.Show));
        await Task.Delay(1000);
        await Task.Run(() => Dispatcher.Invoke(window.Close));
    }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/21 11:12

    回答ありがとうございます
    最終的には自己解決してしまったのですが,それに至るまでのデバッグでいただいた方法で試させていただきうまく動くことを確認致しました

    因みにですが,このソースの場合,window.show,closeの二行に関してawait Task.Run(略)する必要はあるのでしょうか?
    button_clickがもともとUIスレッドなので,地べたでwindow.showすればDispatcheに処理をお願いすることもなくなるのかな?と思いました
    (と思い試してみたところやはりちゃんと動きました)

    マイコンで遊んでいると,C#まで組込みチックな記述になってしまいます…

    キャンセル

  • 2020/01/21 11:15

    > await Task.Run(略)する必要はあるのでしょうか?
    貴方が書いた題意です。
    > 別スレッド(Task.Run)からモードレスウインドウを開いたり閉じたりしたい

    キャンセル

  • 2020/01/21 11:20

    > 貴方が書いた題意です。
    承知いたしました.
    私自身の知識不足によりTask.Run以外思いつかなかったためそのように記載しましたが不適切でした
    質問タイトルを少し編集しておきます

    本意は
    別スレッドで重たい処理をしながらそれに合わせてモードレスウインドウを開いたり閉じたりしたい,です

    ありがとうございました

    キャンセル

0

UI データを更新するときには、thread 番号0をいつも使わなければいけません。

これではどうでしょう。

Application.Current.Dispatcher.Invoke((Action)(() =>{
        mw.show();
      }));

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/01/21 11:16

    回答ありがとうございます
    本件自体は自己解決してしまったのですが,質問があります

    Dispatcherは特に指定しなければthis(MainWindow)を指すことになりますが,Application.Currentは誰を指すのでしょうか

    キャンセル

  • 2020/01/21 11:32

    application には、二次的な domain も存在します。二次 domain がある場合は、Application.Current が必要です。

    キャンセル

  • 2020/01/21 11:39

    ごめんなさい,二次的なDomainとは何でしょうか…
    C#+domainで検索してみたのですがDDDくらいしか見つかりませんでした

    キャンセル

  • 2020/01/21 12:03

    AppDomain.CreateDomain で検索して見てください。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.06%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る

  • トップ
  • WPFに関する質問
  • WPF,別スレッド(Task.Run)で重たい処理をしながらそれに同期してモードレスウインドウを開いたり閉じたりしたい