10

解決しました

オリバーは正しいようです。何度か試した後、例外が発生し、デバッグモードでは確実に発生します。したがって、これはすべてタイミングに関するものでなければなりません。Matthew wattsonsの回答も確認する必要があります;)

まず第一に、私の混乱を説明する小さな例です。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;

namespace testCrossThreading
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            new Thread(ThreadJob).Start();
        }

        void ThreadJob()
        {
            //label1.Text = "1";
            changeText(label1, "1");
        }

        void changeText(Label L, String message)
        {
            L.Text = message;
        }
    }
}

質問

さて、私の質問です。label1.Text = "1";関数 "ThreadJob"でコメントを外すと、期待どおりにクロススレッド例外が発生します。しかし、例が示すようにコメントを残しておくと、機能します。しかし、なぜ?関数はサブスレッドによって呼び出され、私は何も呼び出しません。したがって、ラベルimoのテキストを変更するのはサブスレッドであり、GUIスレッドではありません。それとも私は何かが足りないのですか?

このように書きます。

void ThreadJob()
        {
            Action a = () => label1.Text = "1";
            this.Invoke(a);
        }
4

2 に答える 2

7

単にタイミングの問題だと思います。非 GUI スレッドから GUI 要素を更新しようとすると、クロススレッド例外がスローされる可能性があります。を呼び出して、クロススレッド例外全体を無効にすることもできます

Form.CheckForIllegalCrossThreadCalls = false;

しかし、例外がなくなった後、それ以降の動作は未定義であり、非常に微妙なバグにつながる可能性があります. したがって、コードの匂いのヒントとして例外を取り上げますが、例外がスローされるべきであってもスローされない場合があることに注意してください。

于 2013-03-15T10:34:45.940 に答える
2

競合状態になっている可能性があると思います。そのため、結果はさまざまです。

Text現在表示されていないコントロールのプロパティを変更しようとすると、.Net はどのスレッドがそれを変更するかを気にしません。

コードでは、コンストラクターからスレッドを開始します。実際にフォームを表示するコードは、プロパティを設定するスレッド内のコードが実行される前にフォームを表示する場合と表示しない場合があります。

プロパティを設定するために追加の関数を呼び出すと、タイミングが変化し、競合状態が発生します。

Thread.Sleep(100)の先頭にa を追加することで、これをテストできますThreadJob()

于 2013-03-15T10:42:36.133 に答える