队列函数调用为char写char

时间:2013-12-18 14:59:13

标签: c#

应该做什么

我正在尝试将一些char的文本字符写入TextBlock。我正在使用此代码:

void WriteTextCharForChar(String text)
{
    new Thread(() =>
    {
        foreach(Char c in text)
        {
            TxtDisplayAppendText(c.ToString());
            Thread.Sleep(rnd.Next(20, 100));
        }

        Thread.CurrentThread.Abort();
    }).Start();
}

问题

问题是,当多次调用此方法时,文本会变得混杂。我需要的是一种队列或等待任何方式,直到当前文本写入TextBlock。 诅咒我对任何其他解决方案持开放态度。谢谢!

1 个答案:

答案 0 :(得分:2)

所以这里有几个选项。

  1. 你可以在线程的工作周围添加lock,这样一次就不会有多个运行。

    但这有几个问题:

    1. 不一定按顺序处理这些项目
    2. 你创造了很多线程,所有这些线程都花费了他们几乎所有的时间等待;这非常浪费资源。
  2. 您可以创建一个线程安全队列(BlockingCollection最好),然后从中读取一个线程并在UI线程添加到队列时写出结果

    这也有问题。最值得注意的是,你正在创建一个基本上所有时间都在等待的新线程。这可能比#1好,但不是很多。

  3. 您可以完全避免使用多个线程并以异步方式执行所有操作。任务并行库为您提供了许多工具来帮助解决这个问题。这是最好的选择,因为它会导致创建0个额外的线程。

  4. 首先,我们将创建一个辅助方法来处理文本本身的写入,以便另一个线程可以处理这些调用的“调度”。使用await编写此方法会更容易。需要注意的一个要点是,不是在未知的时间段内阻塞当前线程,而是使用Task.Delay在将来的某个时刻继续执行而不会阻塞线程:

    private async Task WriteText(string text)
    {
        foreach (char c in text)
        {
            TxtDisplayAppendText(c.ToString());
            await Task.Delay(rnd.Next(20, 100));
        }
    }
    

    现在为您的方法。我们可以管理我们的队列,但实际上是一个链接的任务列表。如果我们有一个类型Task的单个字段代表“上一个任务”,我们可以让每个方法调用为该任务添加一个延续,然后将自己设置为前一个任务。下一个任务将自己设置为继续,等等。每个继续将在前一个任务运行时触发,或者如果前一个任务已经完成则立即运行,因此这有效地为我们提供了“队列”。请注意,由于从UI线程调用了WriteTextCharForChar,因此这些调用都已经同步,因此无需lock围绕此任务的操作。

    private Task previousWrite = Task.FromResult(false); //already completed task
    private void WriteTextCharForChar(String text)
    {
        previousWrite = previousWrite.ContinueWith(t => WriteText(text))
            .Unwrap();
    }