C#手动停止异步for语句(打字机效果) [英] C# Manually stopping an asynchronous for-statement (typewriter effect)

查看:30
本文介绍了C#手动停止异步for语句(打字机效果)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 C# .NET-Framework 制作复古风格的游戏,并且为了进行对话,我使用了for语句,该语句会打印我的文字字母按字母(像打字机效果):

I'm making a retro-style game with C# .NET-Framework, and for dialogue I'm using a for-statement, that prints my text letter by letter (like a typewriter-effect):

我正在处理不同的场景,并且有一个跳过按钮(右下),该按钮跳过当前对话并传递到下一个场景.显示所有文本时,我的打字机效果会自动停止,但是当我单击跳过"按钮时,它会自动跳至下一个场景.

I'm working with different scenes, and I have a skip button (bottom right) that skips the current dialogue and passes to the next scene. My typewriter-effect automatically stops when all the text is displayed, but when I click on the skip button, it automatically skips to the next scene.

我希望在打字机仍处于活动状态时,如果单击跳过"按钮,它将首先显示所有文本,而不是跳至下一场景.

I would like it, when the typewriter is still active, and if I click on the skip button, that it first shows all the text, instead of skipping to the next scene.

因此,仅当显示所有文本(自动或手动)时,它才会跳到下一个场景.

So that it only skips to the next scene when all the text is displayed (automatically or manually).

这是我用于打字机方法(+变量)的(工作代码):

This is the (working code) that I'm using for my typewriter method (+ variables):

    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 )的代码:

And this is the code that I want to get for my skip button (named 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语句以查看打字机是否仍处于活动状态,但是我还没有任何工作.

But I don't know how to formulate the 2nd part of code. I've tried many different approaches, like using counters that increase on a buttonclick (and using that to check in an if-statement), and many different types of if-statements to see if the typewriter is still active or not, but I haven't got anything to work yet.

这是需要加载不同组件(单击按钮时)的顺序,这与更新不同变量的方式有关:

This is the sequence in which different components need to be loaded (on button click), which is related to the way different variables are updated:

  1. Gamestate_Cycle()->要求加载新场景.
  2. FullTextBottom = LblTextBottom.Text ->调用以刷新打字机变量.
  3. TypeWriterEffectBottom()->调用以执行打字机效果.
  1. Gamestate_Cycle() --> called for loading new scene.
  2. FullTextBottom = LblTextBottom.Text --> called to refresh variables for typewriter.
  3. TypeWriterEffectBottom() --> called to perform typewriter effect.

推荐答案

避免异步无效.否则,您会得到一个 Exception ,它将破坏您的游戏,并且您将无法捕获它.

Avoid async void. Otherwise you can get an Exception that will break your game and you will not able to catch it.

然后在 async 方法中使用尽可能少的全局变量.

Then use as less global variables in async methods as possible.

我建议 CancellationTokenSource 作为停止Type Writer的线程安全方式.

I suggest CancellationTokenSource as thread-safe way to stop the 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.它是线程安全的,因此可以在全局范围内使用它.

Define CTS. It's thread-safe, so it's ok to have it in global scope.

private CancellationTokenSource cts = null;

async 方法调用TypeWriter,使其能够等待.

Call TypeWriter from async method to be able to await it.

// 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语句(打字机效果)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆