1

私はグーグルで特定の時間にラベルを表示することを可能にする方法を検索しました、そして私はこれを見つけました:

public void InfoLabel(string value)
        {
            if (InvokeRequired)
            {
                this.Invoke(new Action<string>(InfoLabel), new object[] { value });
                return;
            }
            barStaticItem3.Caption = value;

            if (!String.IsNullOrEmpty(value))
            {
                System.Timers.Timer timer = new System.Timers.Timer(6000) { Enabled = true };
                timer.Elapsed += (sender, args) =>
                {
                    this.InfoLabel(string.Empty);
                    timer.Dispose();
                };
            }

        }

私は本当にこの方法を特別に理解することはできません:

-なぜ使用したのですか:InvokeRequired

-この方法は何のために:this.Invoke()

-これは何のためですか:new Action<string>(InfoLabel)

-なぜその記号を使用したのですか:=>

4

4 に答える 4

4

すべてのinvoke関連のものは、そのコードを書いた人が間違って使用したためですTimer(言語にはかなりの数があります)。ここで使用する必要がありSystem.Windows.Forms.Timerます。

public void InfoLabel(string value)
{
    System.Windows.Forms.Timer timer = new Timer();

    timer.Interval = 1000;//or whatever the time should be.
    timer.Tick += (sender, args) =>
        {
            label1.Text = value;
            timer.Stop();
        };
    timer.Start();
}

フォームタイマーには、サンプルにあるコードと同様のことを行う独自の実装内のコードが含まれます(ただし、これは特に厄介な方法であることがわかります)。これにより、TickイベントがUIスレッドで実行されるようになるため、ボイラープレートコードをすべて追加する必要がなくなります。

=>ラムダ式です。senderこれは、2つのパラメーターとを受け取る新しい匿名メソッドを定義する方法ですargs

Taskタイマーを使用する代わりに、sを使用してこの問題を解決することもできます。

public void InfoLabel2(string value)
{
    Task.Factory.StartNew(() => Thread.Sleep(1000)) //could use Task.Delay if you have 4.5
        .ContinueWith(task => label1.Text = value
            , CancellationToken.None
            , TaskContinuationOptions.None
            , TaskScheduler.FromCurrentSynchronizationContext());
}
于 2012-10-05T15:22:17.527 に答える
3

多くの質問!

InvokeRequiredこれは、アプリケーションのマルチスレッドの性質によるものです。UIベースのアプリケーションには、ユーザーインターフェイスのすべての更新が行われるUIスレッドがあります。非UIスレッドからコントロールのメンバーを更新すると、クロススレッド例外がスローされます。Invokeを使用すると、更新がUIスレッドにマーシャリングされます。これは有効です。

Action<string>メソッドのデリゲートです。渡された引数を使用してデリゲートが呼び出されると、InfoLabelメソッドが呼び出されます(例:action.Invoke( "someString"))。=>は、名前付きメソッドを指す代わりに実行される匿名メソッド(名前のないメソッドなど)を作成するために使用されるラムダ式です。

于 2012-10-05T15:20:44.717 に答える
3

InvokeRequiredフォームを作成したスレッドでコードが現在実行されているかどうかを確認します。そうでない場合、WinFormsコードはスレッドセーフではないため、関数はDIDがフォームを作成したスレッドでそれ自体を呼び出す必要があります。

アクションは、文字列を受け取る関数を記述するデリゲート型です(InfoLabel関数を参照してください。これが参照しています)。

 this.Invoke(new Action<string>(InfoLabel), new object[] { value });

上記は言っています。関数InfoLabelからタイプActionの新しいデリゲートを作成し、これを作成したスレッドを使用して呼び出してください。呼び出すときに、オブジェクト'value'を渡します。つまり、フォームを作成したスレッドでInfoLabel(value)を呼び出します。直後に関数から戻るため、関数の「meat」はいずれも間違ったスレッドで実行されないことに注意してください(この時点では間違ったスレッドを使用しています。そうでない場合、InvokeRequiredはtrueになりません)。関数がInvokeによって再度実行されると、関数は正しいスレッド上にあり、InvokeRequiredはfalseになるため、このコードビットは実行されません。

timer.Elapsed += (sender, args) =>
                {
                    this.InfoLabel(string.Empty);
                    timer.Dispose();
                };

上記のコードは、タイマーのElapsedイベントに匿名メソッドを割り当てています。最初のビット(sender、args)はメソッドのパラメーターを記述し、次に=>「ここにメソッドが来る」と言い、その後にコードのブロック(括弧内のすべてのもの)が続きます。

于 2012-10-05T15:24:25.427 に答える
2

InvokeRequired制御が持続InfoLabelするUIスレッドからメソッドを呼び出すかどうかを確認するために使用されます。barStaticItem3スレッドが異なる場合(InvokeRequired)、同じメソッドがで呼び出されthis.Invoke(new Action<string>(InfoLabel), new object[] { value });ます-これはUIスレッド内から同じメソッドを呼び出します。

timer.Elapsed += (sender, args) =>
            {
                this.InfoLabel(string.Empty);
                timer.Dispose();
            };

このコードは匿名メソッドtimerを作成し、それがのElapsedイベントで呼び出されます。実際には、これは6秒(コストラクションのタイマー間隔)後にラベルをクリアし、timerこの匿名メソッドが1回だけ呼び出されるようにオブジェクトを破棄します。

于 2012-10-05T15:16:33.753 に答える