C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: C#で別スレッドで動作するコントロールをフォームに貼付けたい


(過去ログ 172 を表示中)

[トピック内 6 記事 (1 - 6 表示)]  << 0 >>

■99030 / inTopicNo.1)  C#で別スレッドで動作するコントロールをフォームに貼付けたい
  
□投稿者/ ひろし (1回)-(2022/01/31(Mon) 23:18:47)

分類:[.NET 全般] 

VisualStudio2017 C#で開発を行っております。

タイトルの通りなのですが
メインスレッドで動くフォームに、別スレッドで動作するコントロールを貼り付けたいと考えています。

具体的には、ツールのステータスバーにCPUの占有率(稼働率?)を表示したいと考えています。

初めは Timer コントロールを使用して、定期的にCPUの占有率を表示していましたが、
肝心の重い処理が動作しているときに機能しないという残念な結果になってしまいました。

本来は、「重い処理」の方を別スレッドで動作させるべきなのでしょうが、
諸事情により、そちらの処理は変更することが出来ません。

なにか良い方法をご存じの方がいらっしゃいましたら、ご教示いただけないでしょうか。

よろしくお願いいたします。
引用返信 編集キー/
■99031 / inTopicNo.2)  Re[1]: C#で別スレッドで動作するコントロールをフォームに貼付けたい
□投稿者/ KOZ (211回)-(2022/02/01(Tue) 00:07:10)
No99030 (ひろし さん) に返信
> VisualStudio2017 C#で開発を行っております。
> メインスレッドで動くフォームに、別スレッドで動作するコントロールを貼り付けたいと考えています。
> 具体的には、ツールのステータスバーにCPUの占有率(稼働率?)を表示したいと考えています。

Control.CheckForIllegalCrossThreadCalls プロパティを false にしてみましょう。
これで貼り付けることができるはずです。

別スレッドから操作できないのはデバッガがアタッチしているときで、
exe を直接実行している場合はチェックされていません。

ただ、Font/ForeColor/BackColor などのプロパティを親コントロールから引き継ぐと
問題が出るかもしれないので、その辺は手探りでやってみてください。
# すべてオーナードローすれば大丈夫かも。

引用返信 編集キー/
■99032 / inTopicNo.3)  Re[1]: C#で別スレッドで動作するコントロールをフォームに貼付けたい
□投稿者/ KOZ (212回)-(2022/02/01(Tue) 06:27:18)
No99030 (ひろし さん) に返信
> 本来は、「重い処理」の方を別スレッドで動作させるべきなのでしょうが、
> 諸事情により、そちらの処理は変更することが出来ません。

諸事情って何でしょう?
あるコンポーネントを使っていて、スレッドを起動して動かそうとしても動かないってことであれば
スレッドを STA スレッドにしたら動いたっていう話が別の掲示板でありましたけど。
引用返信 編集キー/
■99033 / inTopicNo.4)  Re[2]: C#で別スレッドで動作するコントロールをフォームに貼付けたい
□投稿者/ KOZ (213回)-(2022/02/01(Tue) 07:17:14)
No99031 (KOZ さん) に返信
> Control.CheckForIllegalCrossThreadCalls プロパティを false にしてみましょう。
> これで貼り付けることができるはずです。

すみません。Controls.Add でチェックされていたようです。
SetParent API を使いましょう。

using System;
using System.Drawing;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;
using Timer = System.Windows.Forms.Timer;

public partial class Form1 : Form
{
    public Form1() {
        InitializeComponent();
        var th = new Thread(new ParameterizedThreadStart(OtherThread));
        th.Start(this);
    }

    [DllImport("user32.dll", SetLastError = true)]
    static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);

    private static void OtherThread(object args) {
        Form mainForm = args as Form;
        if (mainForm != null) {
            var subForm = new ThreadForm();
            subForm.Visible = true;
            subForm.Location = Point.Empty;
            subForm.Size = new Size(100, 20);
            Control.CheckForIllegalCrossThreadCalls = false;
            //mainForm.Controls.Add(subForm); // ダメ!チェックがかかっている
            SetParent(subForm.Handle, mainForm.Handle);
            Application.Run(subForm);
        }
    }

    private class ThreadForm : Form
    {
        Timer timer;

        public ThreadForm() {
            TopLevel = false;
            FormBorderStyle = FormBorderStyle.None;
            ControlBox = false;
            timer = new Timer();
            timer.Interval = 1000;
            timer.Tick += Timer_Tick;
            timer.Start();
        }

        private void Timer_Tick(object sender, EventArgs e) {
            Invalidate();
        }

        protected override void OnPaint(PaintEventArgs e) {
            e.Graphics.Clear(Color.White);
            using (var f = new Font("MS UI Gothic", 9.75F)) {
                TextRenderer.DrawText(e.Graphics, DateTime.Now.ToString("hh:mm:ss"),f, Point.Empty, Color.Black);
            }
            base.OnPaint(e);
        }
    }

    private void button1_Click(object sender, EventArgs e) {
        Thread.Sleep(10000); // 重い処理
    }
}

重い処理を実行しても時刻が更新されています。

引用返信 編集キー/
■99042 / inTopicNo.5)  Re[2]: C#で別スレッドで動作するコントロールをフォームに貼付けたい
□投稿者/ ひろし (2回)-(2022/02/01(Tue) 22:22:54)
No99032 (KOZ さん) に返信
> ■No99030 (ひろし さん) に返信
>>本来は、「重い処理」の方を別スレッドで動作させるべきなのでしょうが、
>>諸事情により、そちらの処理は変更することが出来ません。
>
> 諸事情って何でしょう?
> あるコンポーネントを使っていて、スレッドを起動して動かそうとしても動かないってことであれば
> スレッドを STA スレッドにしたら動いたっていう話が別の掲示板でありましたけど。

コメントありがとうございます。

諸事情というのは、ツールの本体に重い処理が多数あり、すべてスレッド化するのが難しいというのと
デグレードの危険性があるので、手を付けない様に言われているためです・・・
引用返信 編集キー/
■99043 / inTopicNo.6)  Re[3]: C#で別スレッドで動作するコントロールをフォームに貼付けたい
□投稿者/ ひろし (3回)-(2022/02/01(Tue) 22:24:44)
No99033 (KOZ さん) に返信
> ■No99031 (KOZ さん) に返信
>>Control.CheckForIllegalCrossThreadCalls プロパティを false にしてみましょう。
>>これで貼り付けることができるはずです。
>
> すみません。Controls.Add でチェックされていたようです。
> SetParent API を使いましょう。
>
> using System;
> using System.Drawing;
> using System.Runtime.InteropServices;
> using System.Threading;
> using System.Windows.Forms;
> using Timer = System.Windows.Forms.Timer;
>
> public partial class Form1 : Form
> {
> public Form1() {
> InitializeComponent();
> var th = new Thread(new ParameterizedThreadStart(OtherThread));
> th.Start(this);
> }
>
> [DllImport("user32.dll", SetLastError = true)]
> static extern IntPtr SetParent(IntPtr hWndChild, IntPtr hWndNewParent);
>
> private static void OtherThread(object args) {
> Form mainForm = args as Form;
> if (mainForm != null) {
> var subForm = new ThreadForm();
> subForm.Visible = true;
> subForm.Location = Point.Empty;
> subForm.Size = new Size(100, 20);
> Control.CheckForIllegalCrossThreadCalls = false;
> //mainForm.Controls.Add(subForm); // ダメ!チェックがかかっている
> SetParent(subForm.Handle, mainForm.Handle);
> Application.Run(subForm);
> }
> }
>
> private class ThreadForm : Form
> {
> Timer timer;
>
> public ThreadForm() {
> TopLevel = false;
> FormBorderStyle = FormBorderStyle.None;
> ControlBox = false;
> timer = new Timer();
> timer.Interval = 1000;
> timer.Tick += Timer_Tick;
> timer.Start();
> }
>
> private void Timer_Tick(object sender, EventArgs e) {
> Invalidate();
> }
>
> protected override void OnPaint(PaintEventArgs e) {
> e.Graphics.Clear(Color.White);
> using (var f = new Font("MS UI Gothic", 9.75F)) {
> TextRenderer.DrawText(e.Graphics, DateTime.Now.ToString("hh:mm:ss"),f, Point.Empty, Color.Black);
> }
> base.OnPaint(e);
> }
> }
>
> private void button1_Click(object sender, EventArgs e) {
> Thread.Sleep(10000); // 重い処理
> }
> }
>
> 重い処理を実行しても時刻が更新されています。
>

コメントありがとうございます。

こちらの処理を実際に試してみましたが、まさに希望通りの動作でした。
早速ツールに組み込みたいと思います。

ありがとうございました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -