Winforms C#aync Wait-失去焦点时Gui冻结
我最近决定看看C#5的新的异步/等待特性。出于演示目的,我编写了一个Windows窗体应用程序,允许用户获取一个整数数组,并使用他们选择的排序例程对它们进行排序。除了这个程序之外,我还提供了五个test.dat文件,每个文件都包含从32000个整数开始的未排序数据,每个后续文件的大小都是原来的两倍。程序将文件中的数据读取到一个整型数组中,以备排序 我遇到的问题是GUI冻结,完全没有响应。但是,只有将GUI本身置于后台时,它才会冻结。i、 例如,我看不到它,因为我可能正忙于浏览互联网等。它可能不会立即冻结。有时我可能会让它重新聚焦,但它仍然会工作,但最终会失败。如果我始终保持程序的焦点,GUI将保持完全响应。我可以在屏幕上拖动它。我可以最小化和最大化它。在结果表单显示经过的排序时间之前,一个字幕样式的进度条会显示动画,我可以继续单击按钮等 现在我想补充一点,我不认为这是排序算法本身的问题。我的理由是,当GUI处于焦点时,它可以正常工作。我还有一套完整的单元测试来验证每种算法是否能够正常工作。运行时间似乎是一个问题,因为堆或快速排序等更快的算法可以处理非常大的数据集,而不会导致冻结。最后,我尝试在表单级别(等待任务)和任务本身捕获异常,但似乎没有抛出异常 在过去的两天里,我刚刚研究了async/await,我并不是一个专家,但我最初的想法是,它可能与购买回focus后的GUI重新绘制有关。有人能帮忙吗?以下是代码的部分,以帮助:- 示例SelectionSort例程:-Winforms C#aync Wait-失去焦点时Gui冻结,winforms,sorting,async-await,Winforms,Sorting,Async Await,我最近决定看看C#5的新的异步/等待特性。出于演示目的,我编写了一个Windows窗体应用程序,允许用户获取一个整数数组,并使用他们选择的排序例程对它们进行排序。除了这个程序之外,我还提供了五个test.dat文件,每个文件都包含从32000个整数开始的未排序数据,每个后续文件的大小都是原来的两倍。程序将文件中的数据读取到一个整型数组中,以备排序 我遇到的问题是GUI冻结,完全没有响应。但是,只有将GUI本身置于后台时,它才会冻结。i、 例如,我看不到它,因为我可能正忙于浏览互联网等。它可能不会
public SelectionSort(IStopwatch stopwatch) : base(stopwatch){}
public override async Task<int[]> SortAsync(int[] data, CancellationToken cancelToken)
{
OnStarted();
Stopwatch.Start();
await Task.Run(() =>
{
int i, j;
int min, temp;
for (i = 0; i < data.Length - 1; i++)
{
if (cancelToken.IsCancellationRequested)
return;
min = i;
for (j = i + 1; j < data.Length; j++)
{
if (data[j] < data[min])
min = j;
}
temp = data[i];
data[i] = data[min];
data[min] = temp;
}
}, cancelToken);
Stopwatch.Stop();
OnCompleted(new SortCompleteEventArgs(Stopwatch.ElapsedMilliseconds, data.Length, cancelToken.IsCancellationRequested));
return data;
}
异步代码似乎没有什么问题。当排序后引发OnComplete事件时,主表单中的处理程序将实例化一个新的结果表单并显示它。当窗体失去焦点时,这是失败的。我正在研究为什么会出现这种情况,以及这是否是一个经过深思熟虑的框架设计决策。无论如何,我只是在处理程序中调用了Activate()方法。这使应用程序成为焦点,然后我实例化了新表单,它工作得很好。不管怎样,至少对我来说可以。e、 g:-
private void DisplaySortResults(object sender, SortCompleteEventArgs e)
{
Activate();
_btnCancelSort.Enabled = false;
_progressBar.Style = ProgressBarStyle.Continuous;
var sortResults = new SortResults();
sortResults.BuildResults(e);
sortResults.SetCompletedValues(e);
sortResults.ShowDialog();
}
async
的一个更合适的演示是一个自然的异步操作,即对本地主机服务器的web请求,每个请求都会休眠async
主要不是为CPU密集型工作而设计的,尽管您可以使用Task.Run
,就像这里一样。也就是说,我在你发布的代码中没有看到任何会导致UI响应问题的东西。这很奇怪。这似乎取决于排序算法中引发的OnCompleted事件。如果被注释掉了,没有问题,没有冻结,尽管很明显,结果屏幕现在不会显示。在关注gui的情况下,工作再次正常。当它在后台时失败。几乎被难住了,但仍在努力。有一种感觉,这可能是一个“踢我自己”的时刻。有一件事要检查:确保结果不是每个UI元素(例如,100000个列表项不会很好)。嗨,Stephen。谢谢你的意见。结果数据不是以这种方式使用的。我将编辑我的帖子,因为它实际上冻结在较小的排序数字上。请注意,我说的是“现在”,但我怀疑它一直在这样做,不知何故我错过了它。
private async void StartSorting_Click(object sender, EventArgs e)
{
if (_lBoxSelectedFiles.Items.Count == 0)
{
MessageBox.Show("Select data to sort");
return;
}
_btnCancelSort.Enabled = true;
if (_comboBxAlgorithm.SelectedValue.Equals("SelectSort"))
{
var selectSort = new SelectSort(new SortStopwatch());
selectSort.Completed += DisplaySortResults;
_sorter = new SorterContext(selectSort);
StartProgressBar();
await _sorter.Sort(_dataToSort, _cancelTokenSrcWrapper.Token);
}
private void DisplaySortResults(object sender, SortCompleteEventArgs e)
{
Activate();
_btnCancelSort.Enabled = false;
_progressBar.Style = ProgressBarStyle.Continuous;
var sortResults = new SortResults();
sortResults.BuildResults(e);
sortResults.SetCompletedValues(e);
sortResults.ShowDialog();
}