以下类用于将文本写入控制台,但是以更加时间的方式,比如像this这样的电影中显示字符的方式,问题是我无法获得方法在课堂上作为任务运行,特别是因为我使用计时器,我有多个相互关联的方法。
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
答案 0 :(得分:1)
这是你想要的效果吗?
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
被打印,执行将在string
之后的下一行继续执行。它实际上并不使用Timer
,因为有更合适的基于Task
的机制(Task.Delay
)。
您必须使用一个小“技巧”才能让控制台应用程序正确使用async
await
,因为Main
不能是Task
。只需创建一个AsyncMain
函数,如我的示例所示,并使用Main
从AsyncMain().Wait()
调用它。 C#7.1发布后,您不需要像public static Task Main(string[] args);
(以及其他)will be considered a valid entry point那样执行此操作。
您可以阅读有关here的异步控制台应用程序的其他一些“问题”。
您可以使用async
及其创建的Task
取消对CancellationTokenSource
CancellationToken
的来电。
任何可以取消的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!)
}