下面的类用于将文本写入控制台,但是以一种更定时的方式,比如在电影(如这 )中显示字符的方式,问题是我无法让类中的方法作为任务运行,特别是因为我使用的是计时器,而且我有多个相互链接的方法。
Private NotInheritable Class WriteText
Private Shared i As Integer = 0
Private Shared text As String = ""
Private Shared audio As New Audio
Private Shared audioFile As String = "C:\Users\jamisco\Documents\Sound for Jamisco\beep-29.wav"
Shared call_command As Boolean
Shared timer As New Timer
Public Shared Sub Text2Write(ByVal Text2Type As String, Optional ByVal call_awaitcommand As Boolean = False)
text = Text2Type
call_command = call_awaitcommand
Timer.Interval = typingInterval
Timer.AutoReset = True
Timer.Start()
writing2console = True
FinishedTyping = False
i = 0
AddHandler Timer.Elapsed, AddressOf Tick
audio.Play(audioFile, AudioPlayMode.BackgroundLoop)
While (writing2console)
Console.ReadKey(True)
End While
End Sub
Private Shared Sub Tick(ByVal sender As Object, ByVal e As ElapsedEventArgs)
If (text.Length >= 0 And timer.Enabled) Then
If i < text.Length Then
Console.Write(text(i))
i += 1
Else
Reset()
End If
End If
End Sub
Public Shared Sub StopTyping()
Reset()
End Sub
Private Shared Sub Reset()
Console.WriteLine()
audio.Stop()
'timer.Stop()
timer.Stop()
i = 0
writing2console = False
FinishedTyping = True
If (call_command) Then
_jamisco.AwaitCommand()
End If
End Sub
End Class发布于 2017-08-28 17:16:22
这就是你想要达到的效果吗?

using System;
using System.Threading.Tasks;
namespace asyncConsoleTyping
{
class Program
{
private static Random _rnd = new Random();
public static void Main(string[] args)
{
AsyncMain().Wait();
}
public static async Task AsyncMain()
{
await Type("This is a test");
await Type("This is another test");
await Type("What is your name?");
var name = Console.ReadLine();
await Type($"Hello {name}!");
Console.Read();
}
public static async Task Type(string text)
{
var prevColor = Console.ForegroundColor;
Console.ForegroundColor=ConsoleColor.Green;
foreach (char c in text)
{
Console.Write(c);
await Task.Delay(10 + _rnd.Next(30));
}
Console.WriteLine();
Console.ForegroundColor = prevColor;
}
}
}这是通过一次异步打印字符串来实现的,每个字符串之间都有一个小的随机延迟。它还会在打印时更改文本颜色,然后再进行还原。您可以使用await Type(SomeString)调用它,并且控制台在打印字符时不会锁定。在打印完整个await之后,将在下一行继续执行。它实际上并不使用Timer,因为有更合适的基于Task的机制来实现这一点(Task.Delay)。
为了让控制台应用程序正确地使用async await,您必须使用一个小“技巧”,因为Main不能是Task。只需创建一个AsyncMain函数,如我的示例所示,并使用AsyncMain().Wait()从Main调用它。一旦C# 7.1发布,您就不需要这样做了,就像public static Task Main(string[] args); (以及其他) 将被视为有效的入境点。一样。
对于异步控制台应用程序,您还可以阅读一些关于这里的其他“陷阱”。
您可以通过使用async Task及其创建的CancellationToken取消对CancellationTokenSource的调用。
任何可以取消的Task都应该接受CancellationToken作为参数。该令牌是通过调用Token函数在CancellationTokenSource上创建的。创建源时,可以指定超时值(var cts = new CancellationTokenSource(1000);),也可以从具有令牌引用的任何地方调用Cancel (cts.Cancel)。然后,您的async方法可以将该令牌传递给它等待的任何东西(支持取消)。它还应该定期检查IsCancellationRequested,看看是否应该取消它的工作。
这是支持取消的上述示例的一个版本:
using System;
using System.Threading;
using System.Threading.Tasks;
namespace asyncConsoleTyping
{
class Program
{
private static Random _rnd = new Random();
public static void Main(string[] args)
{
AsyncMain().Wait();
}
public static async Task AsyncMain()
{
await Type("This is a test");
await Type("This is another test");
await Type("What is your name?");
var name = Console.ReadLine();
await Type($"Hello {name}!");
var cts = new CancellationTokenSource(1000); //Auto-cancels after 1 second
try
{
await Type("This String can get canceled via a CancellationToken", cts.Token);
}
catch (Exception ex)
{
Console.ForegroundColor=ConsoleColor.Red;
Console.WriteLine($"Canceled: {ex.Message}");
}
}
public static Task Type(string text)
{
return Type(text, CancellationToken.None); //This overload doesn't support cancellation, but it calls the one that does. Passing in CancellationToken.None allows it to work without checking to see if a "real" token was passed.
}
public static async Task Type(string text, CancellationToken ct)
{
var prevColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
foreach (char c in text)
{
Console.Write(c);
await Task.Delay(10 + _rnd.Next(30), ct); //Pass the Cancellationtoken in to Task.Delay so the delay can be canceled
if (ct.IsCancellationRequested) //Check to see if the task was canceled, if so, exit the loop through the characters.
{
break;
}
}
Console.WriteLine();
Console.ForegroundColor = prevColor;
}
}
}上面的例子显示了取消实际上有一个微妙的错误,它可能导致控制台的颜色不被重置。await Task.Delay(10 + _rnd.Next(30), ct);将在“取消”上抛出异常,而不进入颜色重置代码。可以通过将其更改为:
public static async Task Type(string text, CancellationToken ct)
{
var prevColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Green;
try
{
foreach (char c in text)
{
Console.Write(c);
await Task.Delay(10 + _rnd.Next(30), ct);
}
}
finally
{
Console.WriteLine();
Console.ForegroundColor = prevColor;
}
ct.ThrowIfCancellationRequested(); //Omit this line if you don't want an exception thrown on cancellation (but be aware of the consequences!)
}https://stackoverflow.com/questions/45914120
复制相似问题