我正在尝试从调度程序中获取元素的值。但是,我无法在稍后的代码中全神贯注。我想将进度传给测试箱。
只要在主线程中使用ProductId.Text
,我就得到值。
Task.Run(() =>
{
ProductId.Dispatcher.Invoke(() =>
{
string productId = ProductId.Text;});
Console.WriteLine($"Creating game {productId}");
});
我只想稍后在代码中传递变量productId。有什么想法吗?
答案 0 :(得分:1)
从评论中看来,似乎有一个长期运行的后台进程,需要将更新发布到UI。
使用Progress类和IProgress界面很容易做到。 Enabling Progress and Cancellation in Async APIs中对此进行了描述。 Progress可以引发事件或在创建它的线程上调用Action<T>
回调。 IProgress.Report方法允许其他线程将消息发送到进度
从本文的示例复制而来,此方法在后台线程中处理图像。每次要报告进度时,都会调用progress.Report(message);
async Task<int> UploadPicturesAsync(List<Image> imageList, IProgress<string> progress)
{
int totalCount = imageList.Count;
int processCount = await Task.Run<int>(() =>
{
foreach (var image in imageList)
{
//await the processing and uploading logic here
int processed = await UploadAndProcessAsync(image);
if (progress != null)
{
var message=$"{(tempCount * 100 / totalCount)}";
progress.Report(message);
}
tempCount++;
}
return tempCount;
});
return processCount;
}
所有需要做的就是在启动异步方法之前在UI线程中创建一个新的Progress实例:
void ReportProgress(string message)
{
//Update the UI to reflect the progress value that is passed back.
txtProgress.Text=message;
}
private async void Start_Button_Click(object sender, RoutedEventArgs e)
{
//construct Progress<T>, passing ReportProgress as the Action<T>
var progressIndicator = new Progress<int>(ReportProgress);
//load the image list *before* starting the background worker
var folder=txtPath.Text;
var imageList=LoadImages(folder);
//call async method
int uploads=await UploadPicturesAsync(imageList, progressIndicator);
}
从用户界面阅读
另一个重要的事情是UploadPicturesAsync
不会尝试从UI元素读取其输入,无论它是哪个。它接受所需的输入,图像列表作为参数。这样可以更轻松地在后台运行,更易于测试和修改。
例如,代替从文本框中读取,可以修改代码以显示“文件夹浏览器”对话框。