C#Timer在循环期间抛出错误?

时间:2014-10-16 01:15:10

标签: c# wpf loops timer error-handling

这里的代码显示了"类型的作家效果"我曾经习惯将文本输出打印给用户。基本上它使用类型编写器效果打印出文本。但它引发了一个错误:

  

“索引和长度必须指代字符串中的位置”

这是我的代码:

private void TypeWriterTimer_Tick(object sender, EventArgs e)
        {
            const int MaxRetries = 5;

            for (int i = 0; i < MaxRetries; i++)
            {
                try
                {
                    Action final = () => dialogBox.Text = typeWriterReply.Substring(0, TypeWriter_index_Num) + "_";//Substring is a part of Type_Text String that we declared at the start
                    dialogBox.Dispatcher.Invoke(final, null);

                    TypeWriter_index_Num++;//Doing a post fix
                    if (TypeWriter_index_Num == typeWriterReply.Length +1)//An if statment with a condition of course
                    {
                        TypeWriter_index_Num = 0;
                        TypeWriterTimer.Stop();
                    }
                    dialogBox.Focus();
                    dialogBox.CaretIndex = dialogBox.Text.Length;
                    dialogBox.ScrollToEnd();

                    break;
                }
                catch (Exception tw)
                {
                    MessageBoxResult result = MessageBox.Show("Type Writer ERROR");
                    Console.WriteLine(tw.ToString());
                }
            }
        }

TypeWriterReply是正在打印的文本,所有变量都是全局声明的。

为什么会抛出此错误?

2 个答案:

答案 0 :(得分:1)

这是一个快速而又脏的打字机效果,目前我正在循环播放文本,但你可以改为停止计时器。

enter image description here

XAML:

<Window x:Class="WpfApplication4.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow"
        Width="525"
        Height="350">
    <Grid>
        <TextBlock x:Name="TextBlock1" />
    </Grid>
</Window>

代码:

using System;
using System.Timers;
using System.Windows;

namespace WpfApplication4
{
    public partial class MainWindow
    {
        private int _length;
        private string _text;

        public MainWindow() {
            InitializeComponent();
            Loaded += MainWindow_Loaded;
        }

        private void MainWindow_Loaded(object sender, RoutedEventArgs e) {
            _text = "Hello, world !";
            var timer = new Timer(100);
            timer.Elapsed += timer_Elapsed;
            timer.Start();
        }

        private void timer_Elapsed(object sender, ElapsedEventArgs e) {
            _length++;
            if (_length > _text.Length) _length = 0;
            var substring = _text.Substring(0, _length);
            Dispatcher.BeginInvoke((Action) (() => { TextBlock1.Text = substring; }));
        }
    }
}

编辑:这里有一个停止在最后的版本

private void timer_Elapsed(object sender, ElapsedEventArgs e) {
    _length++;
    if (_length > _text.Length) {
        Timer timer = (Timer)sender;
        timer.Stop();
        return;
    }
    var substring = _text.Substring(0, _length);
    Dispatcher.BeginInvoke((Action) (() => { TextBlock1.Text = substring; }));
}

答案 1 :(得分:1)

使用C#的async / await非常棒的更短,更简单,更漂亮的方式:

<Window x:Class="WpfApplication5.TypeWriter"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="TypeWriter" Height="300" Width="300">
    <TextBox x:Name="TextBox"/>
</Window>

代码背后:

public partial class TypeWriter : Window
{
    public TypeWriter()
    {
        InitializeComponent();

        TypeText();
    }

    public async void TypeText()
    {
        await Task.Delay(1000);

        var text = "Hello, World! I'm simulating typing into this TextBox.";

        foreach (var character in text)
        {
            this.TextBox.Text += character;

            await Task.Delay(100);
        }
    }
}