【问题标题】:Delay in a WinForms app without using "await Task.Delay(x)"延迟 WinForms 应用程序而不使用“await Task.Delay(x)”
【发布时间】:2016-02-14 20:08:11
【问题描述】:

我正在创建一个扑克应用程序,我想对掷牌效果进行某种模拟,并这样做我目前使用await Task.Delay(x); 但是这需要异步任务,如果我在我做的地方切换此方法task.delay(x) 到异步我也必须将至少 5-6 更改为异步。我想这对于了解异步工作方式的人来说很好。目前我遇到了很多逻辑错误,仅仅是因为我显然不知道 async 和 await 运算符是如何工作的。换句话说,我是新手,有没有其他方法可以替代这条确切的行 await Task.Delay(x); 我不会使用其他任何东西仅这条线连接到异步。

代码如下:

private async Task Shuffle()
{
    Bitmap refreshBackImage = new Bitmap(getBack);
    bCall.Enabled = false;
    bRaise.Enabled = false;
    bFold.Enabled = false;
    bCheck.Enabled = false;
    MaximizeBox = false;
    MinimizeBox = false;
    bool check = false;
    horizontal = tbChips.Left - _settings.Width * 2 - 15;
    vertical = pbTimer.Top - _settings.Height - (_settings.Height) / 7;
    RNGCrypto random = new RNGCrypto();
    for (i = ImgLocation.Length; i > 0; i--)
    {
        int j = random.Next(i);
        string k = ImgLocation[j];
        ImgLocation[j] = ImgLocation[i - 1];
        ImgLocation[i - 1] = k;
    }
    for (i = 0; i < 17; i++)
    {
        Deck[i] = Image.FromFile(ImgLocation[i]);
        string[] charsToRemove = { getCards, ".png", "\\" };
        foreach (string c in charsToRemove)
        {
            ImgLocation[i] = ImgLocation[i].Replace(c, string.Empty);
        }
        Reserve[i] = int.Parse(ImgLocation[i]) - 1;
        Holder[i] = new PictureBox
        {
            SizeMode = PictureBoxSizeMode.StretchImage,
            Height = _settings.Height,
            Width = _settings.Width
        };
        Controls.Add(Holder[i]);
        Holder[i].Name = "pb" + i;
        await Task.Delay(150);

        #region Throwing Cards
        SetPlayers(Player, i, ref check, 560, 470, refreshBackImage);
        SetPlayers(Bot1, i, ref check, 15, 420, refreshBackImage);
        SetPlayers(Bot2, i, ref check, 75, 65, refreshBackImage);
        SetPlayers(Bot3, i, ref check, 590, 25, refreshBackImage);
        SetPlayers(Bot4, i, ref check, 1115, 65, refreshBackImage);
        SetPlayers(Bot5, i, ref check, 1160, 420, refreshBackImage);
        if (i >= 12)
        {
            Holder[12].Tag = Reserve[12];
            if (i > 12) Holder[13].Tag = Reserve[13];
            if (i > 13) Holder[14].Tag = Reserve[14];
            if (i > 14) Holder[15].Tag = Reserve[15];
            if (i > 15)
            {
                Holder[16].Tag = Reserve[16];

            }
            if (!check)
            {
                horizontal = 410;
                vertical = 265;
            }
            check = true;
            if (Holder[i] != null)
            {
                Holder[i].Anchor = AnchorStyles.None;
                Holder[i].Image = refreshBackImage;
                //Holder[i].Image = Deck[i];
                Holder[i].Location = new Point(horizontal, vertical);
                horizontal += 110;
            }
        }

        #endregion

        Bot1 = (Bot)FoldedPlayer(Bot1);
        Bot2 = (Bot)FoldedPlayer(Bot2);
        Bot3 = (Bot)FoldedPlayer(Bot3);
        Bot4 = (Bot)FoldedPlayer(Bot4);
        Bot5 = (Bot)FoldedPlayer(Bot5);
        if (i == 16)
        {
            if (!restart)
            {
                MaximizeBox = true;
                MinimizeBox = true;
            }
            Turns();
        }
    }
    Ending();
}

【问题讨论】:

  • 请出示您的代码。
  • 学习关于异步而不是问这个问题对你来说不是更有意义吗?

标签: c# .net winforms asynchronous async-await


【解决方案1】:

对于动画之类的东西,您可能需要System.Windows.Forms.Timer 组件,它会引发一个周期性事件。

您可以配置间隔以及暂时完全禁用它。

请注意,在延迟之后,您将回到处理函数的顶部...它不会像 await 关键字在下一个自动恢复的方式自动跟踪您在序列中的位置线。所以你需要一些计数器或类似的东西来让你知道接下来动画的哪一步。

【讨论】:

  • @usr:是和不是。对定时代码的更改将是侵入性的,但游戏逻辑可以TimerCardThrown.Enabled = true; 继续。
  • 正是这种恢复造成了一些麻烦,我正处于我的项目中间。是的,我会看看异步,但一旦我完成了..
  • @usr:真正的问题是违反了单一职责原则。 “Shuffle”方法目前至少负责三件事:随机卡牌顺序,将它们与玩家关联,以及 UI 动画,并无缘无故地混入了一些文件访问。如果将它们分开,使用 await 或 Timer 编写动画将是微不足道的。
  • 你能告诉我我应该如何分离方法或者哪些部分应该在新方法中重构
  • @denis:我提到的三件事中的每一件事都应该是一个单独的函数。请注意,您不必完全遵循现实世界——即使在现实世界中,一张牌从牌堆中取出,然后穿过桌子,然后被添加到玩家的手中,在电脑游戏中它是完美的合理地计算出每手牌将在大约 2 纳秒内出现的所有牌,然后启动动画,在几秒钟内直观地描绘发牌过程。
【解决方案2】:

我不确定您是否要执行异步,因为它在完成之前不会回来。意思是如果你想要一些定时的东西。 Async 会为你提供这个有一些麻烦。因为您要么必须等待可能是问题的响应。特别是如果它是一个游戏。看看调试中的异步函数是如何工作的,你就会明白了。事件触发器,或者只是一个定时事件会更好地工作,因为您可以控制它何时触发或等待事件多长时间。这将消除您的延迟,或者应该。

在您的情况下,当时的一个简单触发事件将显示投掷纸牌,完成后将继续执行您的功能。这很简单,你可能需要做一些事情,比如等到触发器完成。无论哪种方式,都有大量有关事件的信息。在你去异步之前看看。由于它是表单,因此您可以随心所欲地进行操作,如果它用于 windows phone 或其他类型的系统,则某些系统只需要异步。

这应该会有所帮助: https://msdn.microsoft.com/en-us/library/wkzf914z(v=vs.90).aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-04-20
    • 1970-01-01
    • 2018-09-09
    • 1970-01-01
    • 2021-02-14
    • 1970-01-01
    • 2021-10-16
    • 2015-01-23
    相关资源
    最近更新 更多