我有6张图片名为image_1,image_2 ...现在我想在图片框中以随机顺序显示这些图片,所以我创建了这段代码:
for (int i = 0; i < 10; i++)
{
diceBox.ImageLocation = "images/dice_" + rn.Next(1,6).ToString() + ".png";
diceBox.Update();
Task.Delay(1000);
}
但这不起作用。它只显示其中一张图片。我觉得它正在跳过&#34; Task.Delay(1000)&#34;,我该如何解决这个问题?
答案 0 :(得分:2)
代码问题不是Task.Delay(1000);
。这基本上立即创建了一个任务,其结果从未被查看过,但调用它的代码会立即继续前进。它没有等待任务完成。它在这段代码中实际上是一个无操作。
问题在于,即使使用diceBox.Update()
,用户界面也无法实际重绘控件。 for
循环阻止UI进行任何重绘。因此,在for
循环中选择的最终图像是唯一显示的图像,因为它仅在UI可以更新的循环之后。
诀窍是使用某种计时器来更新控制。我最喜欢的选择是使用微软的Reactive Extensions(NuGet&#34; Rx-WinForms&#34;)。这是代码的样子:
Observable
.Interval(TimeSpan.FromSeconds(1.0))
.Take(10)
.ObserveOn(diceBox)
.Subscribe(fn =>
{
diceBox.ImageLocation = String.Format("images/dice_{0}.png", rn.Next(1, 7));
diceBox.Update();
});
更标准的计时器方法是:
var i = 0;
var timer = new System.Windows.Forms.Timer();
EventHandler handler = null;
handler = (s2, e2) =>
{
diceBox.ImageLocation = String.Format("images/dice_{0}.png", rn.Next(1, 7));
diceBox.Update();
if (++i >= 10)
{
timer.Enabled = false;
timer.Tick -= handler;
timer.Dispose();
}
};
timer.Tick += handler;
timer.Interval = 1000;
timer.Enabled = true;
我喜欢Reactive Extensions方法 - 它从上到下读得很好。标准计时器方法遍布整个地方,但可能更熟悉。
我测试了这两种方法,它们似乎工作正常。