C# 从UI线程外的任务调用Thread.Sleep(n)是否可以冻结UI?
下面的代码抽象了我的实际任务,即遍历位图中的每个像素C# 从UI线程外的任务调用Thread.Sleep(n)是否可以冻结UI?,c#,multithreading,xamarin,C#,Multithreading,Xamarin,下面的代码抽象了我的实际任务,即遍历位图中的每个像素 myButtonCommand.execute(async () => { await Task.Run(() => { while(i++<1000000) { // do some work if(i % 1000 == 0) // only update on every 1000th iteration {
myButtonCommand.execute(async () => {
await Task.Run(() => {
while(i++<1000000) {
// do some work
if(i % 1000 == 0) // only update on every 1000th iteration
{
ProgressChanged.Invoke(this, i); // fire update event
Thread.Sleep(n);
}
}
});
});
myButtonCommand.execute(异步()=>{
等待任务。运行(()=>{
而++
睡眠(n)当任务旋转时,UI线程被阻塞
这意味着您在这里调用的调用太多。
GUI线程没有“阻塞”,只是工作过度
另一种可能更好的方法
//if(i % 1000 == 0)
if(i % 1000000 == 0)
类似,我可以向您保证UI不会冻结。
查找异步进程
等待任务。延迟(500);
可能就是您所需要的
async Task<int> TaskDelayAsync(CancellationToken ct, IProgress<int> progress)
{
int i = 0;
while (true)
{
i++;
//Debug.WriteLine(i);
progress.Report(i);
ct.ThrowIfCancellationRequested();
await Task.Delay(500);
}
return i;
}
async任务taskdayasync(取消令牌ct,IProgress进程)
{
int i=0;
while(true)
{
i++;
//Debug.WriteLine(i);
进度报告(一);
ct.ThrowIfCancellationRequested();
等待任务。延迟(500);
}
返回i;
}
因此,请考虑一下,如果您没有睡眠,您每秒会在该循环中调用多少次ProgressChanged.Invoke()
。ProgressChanged.Invoke()
将调用UI线程上运行的代码。正确的修复方法可能是调用ProgressChanged.Invoke()
的频率要低得多。@MatthewWatson,是的,很多次。我更新了我的答案,让它只在每1000次迭代中调用ProgressChanged.Invoke()
,我忘了在我的“生产代码”中提到这一点也是必要的它使用秒表而不是i%1000=0
使其每秒最多更新10次。它应该每秒管理10次而不会出现任何问题-除非对进度更改事件的响应做了太多的工作。响应只是更新进度条。但奇怪的是,没有线程。Sleep(n)UI被阻塞。如果您想亲眼看到,请提交到存储库。只需注释掉if并编码一条长消息(string.length=a lot)。回答2):显示订阅ProgressChanged
的代码。否决投票,这是生产应用程序中的代码。你发现了什么错误?仅供参考,那不是我。i%1000==0
只是伪代码。我使用秒表,最多每十分之一秒更新一次,但这比我认为应该包含的更详细。总之是的,我认为您的原始答案可能有效。也就是说,使用BeginInvoke。显然调用运行在同一个线程上,但BeginInvoke运行在另一个线程()。我现在无法尝试,但会在发现后尝试更新此问题。BeginInvoke映射到Post,调用发送到您的同步上下文。等待或不等待答案。好吧(BeginInvoke)不起作用。我不想再搞乱它了。我只想让它保持原样,让它执行线程。睡眠(0)
,最多每秒10次。不错,但我讨厌不理解到底发生了什么。