C# 手动停止异步 for 语句(打字机效果)

标签 c# .net winforms

我正在用 C# 制作一款复古风格的游戏.NET-Framework ,对于对话,我使用了一个 for 语句,它会一个字母一个字母地打印我的文本(就像打字机效果一样):
enter image description here
我正在处理不同的场景,我有一个跳过按钮(右下角)可以跳过当前对话并传递到下一个场景。当显示所有文本时,我的打字机效果会自动停止,但是当我单击跳过按钮时,它会自动跳到下一个场景。
我希望在打字机仍处于事件状态时,如果我单击跳过按钮,它首先显示所有文本,而不是跳到下一个场景。
这样它只会在显示所有文本时(自动或手动)跳到下一个场景。
这是我用于打字机方法(+ 变量)的(工作代码):

    public string FullTextBottom;
    public string CurrentTextBottom = "";
    public bool IsActive;
    
    public async void TypeWriterEffectBottom()
    {
        if(this.BackgroundImage != null) // only runs on backgrounds that arent black
        {
            for(i=0; i < FullTextBottom.Length + 1; i++)
            {
                CurrentTextBottom = FullTextBottom.Substring(0, i); // updating current string with one extra letter
                LblTextBottom.Text = CurrentTextBottom; // "temporarily place string in text box"
                await Task.Delay(30); // wait for next update
                
                #region checks for IsActive // for debugging only!

                if(i < FullTextBottom.Length + 1)
                {
                    IsActive = true;
                    Debug1.Text = "IsActive = " + IsActive.ToString();
                }
                if(CurrentTextBottom.Length == FullTextBottom.Length)
                {
                    IsActive = false;
                    Debug1.Text = "IsActive = " + IsActive.ToString();
                }

                #endregion
            }
        }

    }
这是我想为我的跳过按钮(名为 Pb_FastForward)获取的代码:
    private void PbFastForward_Click(object sender, EventArgs e)
    {
        if( //typewriter is active)
        {
             //print all text into the textbox
        }
        
        else if( //all text is printed)
        {
             // skip to the next scene
        }
    }   
但我不知道如何制定代码的第二部分。我尝试了许多不同的方法,例如使用在单击按钮时增加的计数器(并使用它来检查 if 语句),以及许多不同类型的 if 语句来查看打字机是否仍然处于事件状态,但我还没有任何工作。
编辑
这是不同组件需要加载的顺序(点击按钮时),这与不同变量的更新方式有关:
  • Gamestate_Cycle() --> 调用加载新场景。
  • FullTextBottom = LblTextBottom.Text --> 调用以刷新打字机的变量。
  • TypeWriterEffectBottom() --> 调用执行打字机效果。
  • 最佳答案

    避免 async void .否则,您可以获得 Exception这会破坏你的游戏,你将无法catch它。
    然后在 async 中用作较少的全局变量方法尽可能。
    我建议 CancellationTokenSource 作为停止 Type Writer 的线程安全方式。

    public async Task TypeWriterEffectBottom(string text, CancellationToken token)
    {
        if (this.BackgroundImage != null)
        {
            Debug1.Text = "TypeWriter is active";
            StringBuilder sb = new StringBuilder(text.Length);
            foreach (char c in text)
            {
                if (token.IsCancellationRequested)
                {
                    LblTextBottom.Text = text;
                    break;
                }
                sb.Append(c);
                LblTextBottom.Text = sb.ToString();
                await Task.Delay(30);
            }
            Debug1.Text = "TypeWriter is finished";
        }
    }
    
    定义 CTS。它是线程安全的,因此可以在全局范围内使用它。
    private CancellationTokenSource cts = null;
    
    async 调用 TypeWriter方法能够await它。
    // set button layout as "Skip text" here
    using (cts = new CancellationTokenSource())
    {
        await TypeWriterEffectBottom(yourString, cts.Token);
    }
    cts = null;
    // set button layout as "Go to the next scene" here
    
    最后
    private void PbFastForward_Click(object sender, EventArgs e)
    {
        if (cts != null)
        {
            cts?.Cancel();
        }
        else
        {
            // go to the next scene
        }
    }   
    

    关于C# 手动停止异步 for 语句(打字机效果),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62610803/

    相关文章:

    c# - 调试键盘事件,如 'Ctrl+Up Arrow'

    c# - 当我将鼠标悬停在子控件上时会触发鼠标事件

    c# - 继承Form,没有.Designer.cs

    c# - 这个语法在 C# 中的名称是什么(类似多元组的赋值)?

    c# - 在 C# 中使用可空类型

    C# Outlook Mailitem ContextMenu 和 Ribbon 不能一起工作(只能单独使用)

    .net - 如何安装以管理员身份运行的 Windows 服务?

    c# - 如何安全地将可空结果从 sqlreader 转换为 int?

    c# - 模拟测试方法

    c# - 在 .NET 中,finally 是否等同于 try-catch-throw?