2

を使用してリストボックスにテキストを追加したいのですがTask、ボタンを使用してクリックイベントに次のコードを配置するだけです:

TaskScheduler uiScheduler = TaskScheduler.FromCurrentSynchronizationContext();
Task.Factory.StartNew(() =>
{
    for (int i = 0; i < 10; i++)
    {
        listBox1.Items.Add("Number cities in problem = " + i.ToString());
        System.Threading.Thread.Sleep(1000);
    }
}, CancellationToken.None, TaskCreationOptions.None, uiScheduler);

しかし、それは機能せず、for ループの最後まで UI がロックされます。

問題はどこだ ?

ありがとう :)

4

4 に答える 4

4

問題はどこですか?

UIスレッドでタスクを実行したいと明示的に言っています...そして、タスク内でスリープしているため、UIスレッドをブロックしています。問題を引き起こさThread.Sleep ないために、UI スレッドにどのように参加することを期待していましたか?

C# 5 と async/await を使用できる場合は、作業がはるかに簡単になります。

private static async Task ShowCitiesAsync()
{
    for (int i = 0; i < 10; i++)
    {
        listBox1.Items.Add("Number cities in problem = " + i);
        await Task.Delay(1000);
    }
}

(タグで示唆されているように) C# 5 を使用できない場合は、かなりトリッキーです。を使用するのが最善かもしれませんTimer

// Note: you probably want System.Windows.Forms.Timer, so that it
// will automatically fire on the UI thread.
Timer timer = new Timer { Interval = 1000; }
int i = 0;
timer.Tick += delegate
{
    listBox1.Items.Add("Number cities in problem = " + i);
    i++;
    if (i == 10)
    {
        timer.Stop();
        timer.Dispose();
    }
};
timer.Start();

ご覧のとおり、かなり醜いです...そして、UIの更新の間に実際には何もしたくないと想定しています。

別の方法として、 を使用して別のスレッドで長時間実行されるタスク (現在はスリープ状態) をシミュレートしBackgroundWorker、 を使用ReportProgressして UI スレッドに戻ってリスト項目を追加することもできます。

于 2013-07-02T05:50:55.863 に答える
-1

このスレッドの提案に基づいて、次の解決策を考え出しました。

    public TaskGUIUpdater(Form1 form1, TaskDataGenerator taskDataGenerator)
    {
        Task.Factory.StartNew(() => {
            while (true)
            {
                form1.BeginInvoke(new Action(() => {
                    form1.UpdateGUI(taskDataGenerator.Counter, taskDataGenerator.RandomData);
                }));

                Thread.Sleep(1000);
            }
        });
    }

TaskGUIUpdater は、メイン フォーム外のクラスのコンストラクタです。更新する必要があるフォームへの参照と、データを取得する必要があるタスクの参照が必要です。

form1.UpdateGUI メソッドは、form1 に設定するデータを受け取り、それを form1 に設定するだけです。

于 2014-11-21T15:35:44.423 に答える