c# - 使用异步任务和 Textbox.Text = "Hello" 时出现问题
问题描述
首先,抱歉,因为我对 C# 还很陌生,所以我决定提出这个问题,因为我已经为此窒息了好几个小时。
我有一个与 Google Cloud Speech 服务配合使用并进行 Speech-to-Text 操作的 GUI。我与您分享单击按钮时运行的整个方法:
private async Task<object> StreamingMicRecognizeAsync(int seconds)
{
if (NAudio.Wave.WaveIn.DeviceCount < 1)
{
Console.WriteLine("No microphone!");
return -1;
}
GoogleCredential googleCredential;
using (Stream m = new FileStream(@"..\..\credentials.json", FileMode.Open))
googleCredential = GoogleCredential.FromStream(m);
var channel = new Grpc.Core.Channel(SpeechClient.DefaultEndpoint.Host,
googleCredential.ToChannelCredentials());
var speech = SpeechClient.Create(channel);
var streamingCall = speech.StreamingRecognize();
// Write the initial request with the config.
await streamingCall.WriteAsync(
new StreamingRecognizeRequest()
{
StreamingConfig = new StreamingRecognitionConfig()
{
Config = new RecognitionConfig()
{
Encoding =
RecognitionConfig.Types.AudioEncoding.Linear16,
SampleRateHertz = 48000,
LanguageCode = "es-ES",
},
InterimResults = true,
}
});
// Read from the microphone and stream to API.
object writeLock = new object();
bool writeMore = true;
var waveIn = new NAudio.Wave.WaveInEvent();
waveIn.DeviceNumber = 0;
waveIn.WaveFormat = new NAudio.Wave.WaveFormat(48000, 1);
waveIn.DataAvailable +=
(object sender, NAudio.Wave.WaveInEventArgs args) =>
{
lock (writeLock)
{
if (!writeMore) return;
streamingCall.WriteAsync(
new StreamingRecognizeRequest()
{
AudioContent = Google.Protobuf.ByteString
.CopyFrom(args.Buffer, 0, args.BytesRecorded)
}).Wait();
}
};
// Print responses as they arrive.
Task printResponses = Task.Run(async () =>
{
while (await streamingCall.ResponseStream.MoveNext(default(CancellationToken)))
{
foreach (var result in streamingCall.ResponseStream
.Current.Results)
{
foreach (var alternative in result.Alternatives)
{
Console.WriteLine(alternative.Transcript);
//Textbox1.Text = alternative.Transcript;
}
}
}
});
waveIn.StartRecording();
Console.WriteLine("Speak now.");
Result_Tone.Text = "Speak now:\n\n";
await Task.Delay(TimeSpan.FromSeconds(seconds));
// Stop recording and shut down.
waveIn.StopRecording();
lock (writeLock) writeMore = false;
await streamingCall.WriteCompleteAsync();
await printResponses;
return 0;
}
我的问题是我想更新Textbox1
控件的内容,但它不起作用。它将输出完美地写入控制台,Console.WriteLine(alternative.Transcript);
但没有写入我的文本框。
如果有人可以提供帮助,我将非常感谢他的帮助。
解决方案
问题是您正在使用Task.Run
,这意味着您的代码将在线程池线程上运行。
而不是调用Task.Run()
,只需将该代码移动到一个单独的异步方法中:
async Task DisplayResponses(IAsyncEnumerator<StreamingRecognizeResponse> responses)
{
while (await responses.MoveNext(default(CancellationToken)))
{
foreach (var result in responses.Current.Results)
{
foreach (var alternative in result.Alternatives)
{
Textbox1.Text = alternative.Transcript;
}
}
}
}
然后从已经在 UI 线程(例如事件处理程序)上的代码直接(不使用)调用该方法。Task.Run
异步机制将确保在await
表达式之后,您回到 UI 线程(相同的同步上下文)。因此,对属性的分配Text
将发生在 UI 线程上,一切都应该很好。
例如:
// This would be registered as the event handler for a button
void HandleButtonClick(object sender, EventArgs e)
{
var stream = client.StreamingRecognize();
// Send the initial config request
await stream.WriteAsync(...);
// Presumably you want to send audio data...
StartSendingAudioData(stream);
await DisplayResponses(stream.ResponseStream);
}
推荐阅读
- scheme - 方案,连续分数,尾递归
- java - Springboot - application-integration.properties 在 src/main/resources 下工作,但不在 src/test/resources 下工作
- css - 自定义动画角度材质选项卡
- ios - 滚动后 SwiftUI 列表单元格未正确显示选择状态
- python - 如何自动将 json(或任何数据文件,如 csv)同步到 GitHub
- python - 检查元素是否存在时获取子列表的索引
- python - 嗨,我正在尝试使用 python 在 Spyder 中构建一个简单的计算器(只是添加)。如何定义 end 以便删除以前的数字?
- tfs - 如何限制将解决方案添加到团队基础服务器中的源代码控制权限?
- python - 在pygame中使用箭头键更新精灵位置
- vba - 限制用户与工作簿的交互 - 隐藏工作簿/仅显示用户窗体