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

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

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework 3.5

.NET Framework-3.5は、NET Framework 2.0にアセンブリを追加(3.0も含む)したものをベースにしています。

Q&A

解決済

1回答

1104閲覧

別のクラスでの処理中にthreadが止まってしまう

RC46

総合スコア7

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Visual Studio

Microsoft Visual StudioはMicrosoftによる統合開発環境(IDE)です。多種多様なプログラミング言語に対応しています。

.NET Framework 3.5

.NET Framework-3.5は、NET Framework 2.0にアセンブリを追加(3.0も含む)したものをベースにしています。

0グッド

0クリップ

投稿2021/04/27 02:36

前提・実現したいこと

Form上のラベルで処理用クラスでの処理状況を更新したい

発生している問題・エラーメッセージ

処理用クラスで重い処理(fs_Process.Test();)を行っているが、そのクラスでの処理中はthread2内のwhileがループせず止まってしまう状況です
処理用クラスでの処理状況はDispStringClass.dispStringに送り、それを表示しようかと思いましたが、更新されないので、デバッグすると(fs_Process.Test();)完了するまでthread2が止まっているおり、SetLabelのメゾットが走らない状況です

独学で勉強している為、基礎や根本的な部分が抜けていると思いますが、教えていただければと思います

該当のソースコード

C#

1class main:Form 2{ 3 private void Test() 4 { 5 try 6 { 7 thread2 = new Thread(new ThreadStart(() => 8 { 9 while (true) 10 { 11 Invoke(new DispDISP(SetLabel), DispStringClass.dispString()); 12 } 13 })); 14 15 thread2.Start(); 16 fs_Process = new ibmProcess(); 17 fs_Process.Test(); 18 19 thread2.Abort(); 20 thread2.Join(); 21 } 22 catch { } 23 } 24 25 delegate void DispDISP(string strDisp); 26 27 private void SetLabel(string strDisp) 28 { 29 DispLabel.Text = strDisp; 30 } 31} 32 33class ibmProcess 34{ 35 public bool Test() 36 { 37 edpAccess.SessionM_ACon(); 38 edpAccess.SessionACon(); 39 40 DispStringClass.dispString = "処理中1-1"; 41 edpAccess.oiM.WaitForInputReady(5000); 42   ********************重い処理 43 44 DispStringClass.dispString = "処理中1-2"; 45     edpAccess.oiM.WaitForInputReady(5000); 46 ********************重い処理 47 48 DispStringClass.dispString = "処理中1-3"; 49 edpAccess.oiM.WaitForInputReady(5000); 50 ********************重い処理 51 52 edpAccess.psM.SendKeys("[enter]", 1, 1); 53 edpAccess.oiM.WaitForInputReady(5000); 54 55 string stateCheck = edpAccess.psA.GetText(5, 40, 2); 56 int c = 0; 57 58 do 59 { 60 System.Threading.Thread.Sleep(1000); 61 62 if (stateCheck == "OK") { break; } 63 edpAccess.psA.SendKeys("[enter]", 1, 1); 64 edpAccess.oiA.WaitForInputReady(5000); 65 c++; 66 if (c == 40) 67 { 68 return false; 69 } 70 //ステータス確認 71 stateCheck = edpAccess.psA.GetText(5, 40, 2); 72 73 } while (stateCheck != "OK"); 74 75 return true; 76 } 77} 78 79 80 81

試したこと

Application.DoEventsなど試しましたが駄目でした
ibmProcessではIBMのPCCOMMというエミュレーターを操作しております

補足情報(FW/ツールのバージョンなど)

導入PCがイントラネット上のWin7でNetFramework 3.5 しか使えません。

気になる質問をクリップする

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

dodox86

2021/04/27 06:18

質問に直接関係ない指摘ですが、 > SetLabelのメゾットが走らない状況です メゾットではなく、メソッド(method)です。(意外とあるあるな間違い)
RC46

2021/04/27 06:51

回答ありがとうございます。 素人なもので、プログラミング自体もよくこんな細かい記述ミスで混乱することがあるので 気を付けます
guest

回答1

0

ベストアンサー

ご提示のコードでは、重い処理をUIスレッドで実行し、別スレッドから表示をかけようとしています。
重い処理の実行中は、メッセージループが止まっているので別スレッドからの Invoke が止まってしまいます。

重い処理を別スレッドに持って行ってください。
BackgroundWorker を使うと楽に書けると思います。

参考URL:時間のかかる処理をバックグラウンドで実行するには?
https://www.atmarkit.co.jp/fdotnet/dotnettips/436bgworker/bgworker.html

C#

1using System; 2using System.ComponentModel; 3using System.Threading; 4using System.Windows.Forms; 5 6public partial class Form1 : Form 7{ 8 BackgroundWorker worker1; 9 10 public Form1() { 11 InitializeComponent(); 12 worker1 = new BackgroundWorker(); 13 worker1.WorkerReportsProgress = true; 14 worker1.DoWork += worker_DoWork; 15 worker1.ProgressChanged += worker_ProgressChanged; 16 } 17 18 // この中はワーカースレッド 19 private void worker_DoWork(object sender, DoWorkEventArgs e) { 20 var worker = (BackgroundWorker)sender; 21 worker.ReportProgress(0, "処理中1-1"); 22 Thread.Sleep(3000); // 重い処理のかわり 23 worker.ReportProgress(0, "処理中1-2"); 24 Thread.Sleep(3000); // 重い処理のかわり 25 worker.ReportProgress(0, "処理中1-3"); 26 Thread.Sleep(3000); // 重い処理のかわり 27 worker.ReportProgress(0, "完了!!"); 28 } 29 30 // この中は UI スレッド 31 private void worker_ProgressChanged(object sender, ProgressChangedEventArgs e) { 32 DispLabel.Text = (string)e.UserState; 33 } 34 35 private void button1_Click(object sender, EventArgs e) { 36 if (!worker1.IsBusy) { 37 worker1.RunWorkerAsync(); 38 } 39 } 40}

投稿2021/04/27 03:25

KOZ6.0

総合スコア2622

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RC46

2021/04/27 06:49

回答ありがとうございます おっしゃるとおり、スレッドまたはBackgroundWorker内で重い処理をするつもりでしたが、IBMのエミュレーター操作がメインスレッド以外ではなぜか、ハンドルできないとなり処理できないのです。 詳しくは割愛しますが、IBMのエミュレータ―の開発情報が少なく困っているところです システム自体は稼働していますが、やはり処理状況の表示が要望があり、対応しているところです
KOZ6.0

2021/04/27 08:47

エミュレータが動くための要件を調べたほうがいいと思います。 (STA スレッドでないとだめ、とか、メッセージループを回さないとだめ、とか)
RC46

2021/04/30 00:10

回答ありがとうございます IBMのAPI仕様書(クラスライブラリー)にもそれらしきことが書いてなく、COMとSTAの知見が無く、改めて調べてみて、「thread.Start();」の前に「thread.SetApartmentState(ApartmentState.STA);」と記述したらサブスレッドでIBMへのアクセス処理ができるようになりました。 これで、他でUIに関わる細かい部分も色々、改善できそうです。 有り難うございました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問