如何防止GUI在操作期间锁定?

时间:2014-08-18 01:48:21

标签: c# multithreading asynchronous task async-await

这是我的代码:

private void RunCoinFlip()
{
    ToggleControlsUsability();

    Task task = new Task(CoinFlippingAnimation);
    task.Start();
    task.Wait();

    ToggleControlsUsability();

    flipOutcome = picCoin.Image == coinSideImages[0] ? CoinSides.Heads : CoinSides.Tails;
    lblResult.Text = userGuess == flipOutcome ? "Congrats you won!" : "Too bad you lost.";
}

private void ToggleControlsUsability()
{
    btnHeads.Enabled = !btnHeads.Enabled;
    btnTails.Enabled = !btnTails.Enabled;
}

private void CoinFlippingAnimation()
{
    Random rng = new Random();

    for (int i = 0; i < 15; i++)
    {
        int side = rng.Next(0, coinSideImages.Length);
        picCoin.Image = coinSideImages[side];

        Thread.Sleep(100);
    }
}

基本上,按钮应在操作过程中冻结,然后解冻,硬币翻转动画会翻转硬币。不幸的是,GUI在动画期间被锁定,因此您无法移动窗口或调整大小。

我一直在阅读关于异步和等待但我不确定这是否适用于此或如何添加它。我尝试的不同结果总是导致阻塞,即时解冻控件或跨线程执行错误。

1 个答案:

答案 0 :(得分:3)

这里不需要另一个线程,因为时间全部用在Thread.Sleep而不是随机数生成。因此,一个简单的async解决方案将是:

private async Task RunCoinFlipAsync()
{
  ToggleControlsUsability();

  await CoinFlippingAnimationAsync();

  ToggleControlsUsability();

  flipOutcome = picCoin.Image == coinSideImages[0] ? CoinSides.Heads : CoinSides.Tails;
  lblResult.Text = userGuess == flipOutcome ? "Congrats you won!" : "Too bad you lost.";
}

private async Task CoinFlippingAnimationAsync()
{
  Random rng = new Random();

  for (int i = 0; i < 15; i++)
  {
    int side = rng.Next(0, coinSideImages.Length);
    picCoin.Image = coinSideImages[side];

    await Task.Delay(100);
  }
}