C# 异步方法冻结用户界面
预期结果:C# 异步方法冻结用户界面,c#,android,xamarin,xamarin.android,async-await,C#,Android,Xamarin,Xamarin.android,Async Await,预期结果: public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // [...] _fab = root.FindViewById<FloatingActionButton>(...); _fab.Click += ((sender, v) => TestAsync("fab"));
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
await LongTask();
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
UI线程调用TestAsync
,工作线程执行longstask
实际结果:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
await LongTask();
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
Ui线程执行所有操作
测试:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
await LongTask();
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
public override视图OnCreateView(布局、充气机、视图组容器、Bundle savedInstanceState)
{
// [...]
_fab=root.FindViewById(…);
_制造。点击+=((发送方,v)=>TestAsync(“制造”);
// [...]
}
专用异步void TestAsync(字符串源)
{
等待长任务();
}
专用异步任务
{
而(true){}//线程应该挂在这里
}
结果:Ui冻结
测试2:
为了确保UI执行所有操作,我做了一个网络操作(在Android的UI线程中是不允许的)
公共异步任务网络(字符串s)
{
URL=新URL(“http://www.randomtext.me/api/");
Java.IO.BufferedReader reader=new Java.IO.BufferedReader(new Java.IO.InputStreamReader(url.OpenStream());
整数计数=0;
字符串str;
而((str=reader.ReadLine())!=null){
计数+=长度;
}
reader.Close();
wait Task.Delay(3000);//确保此方法编译为异步方法,即使它不是必需的
返回计数;
}
结果:NetworkOnMainThreadException
问题:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
// By not calling await you tell the code that you don't need this
// calling method to await a return value.
// using Task.Run explicitly requests another thread process this request
Task.Run(LongTask);
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
为什么工作线程中不执行longstask
或Network
方法?那么,等待
/异步
的是什么
谢谢
工作线程执行长任务
不,这不会自动发生。您等待GUI线程,因此将阻止它。此模式对于异步I/O是可以的,因为这将释放线程
但是,当您的案例受CPU限制时,异步/等待没有任何用处,请使用任务。运行:
private void TestAsync(string origin)
{
Task.Run( LongTask);
}
工作线程执行长任务
不,这不会自动发生。您等待GUI线程,因此将阻止它。此模式对于异步I/O是可以的,因为这将释放线程
但是,当您的案例受CPU限制时,异步/等待没有任何用处,请使用任务。运行:
private void TestAsync(string origin)
{
Task.Run( LongTask);
}
主要规则是:
- 与ui相关的行为必须在主线程(ui线程)中
- 网络/繁重任务必须在非主(ui)线程中执行
- 在doInBackground方法中创建您的网络逻辑李>
- 然后在onPostExecute方法中更新UI
- 与ui相关的行为必须在主线程(ui线程)中
- 网络/繁重任务必须在非主(ui)线程中执行
- 在doInBackground方法中创建您的网络逻辑李>
- 然后在onPostExecute方法中更新UI
参考:任务一:异步/等待
private async void TestAsync(string origin)
{
await LongTask();
}
说明:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
// By not calling await you tell the code that you don't need this
// calling method to await a return value.
// using Task.Run explicitly requests another thread process this request
Task.Run(LongTask);
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
调用按钮click事件委托时,将从主调度程序(UI线程)调用该委托。它告诉代理同步调用TestAsync(“Fab”)
。当代理运行test async方法时,会告诉它运行任务LongTask
,但您也会告诉它使用“wait”请求等待该任务的结果。因此,TestAsync
方法在longstask
完成之前无法完成;由于这是从主调度器请求的,UI的其余部分将挂起,直到完成为止
分辨率:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
// By not calling await you tell the code that you don't need this
// calling method to await a return value.
// using Task.Run explicitly requests another thread process this request
Task.Run(LongTask);
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
public override视图OnCreateView(布局、充气机、视图组容器、Bundle savedInstanceState)
{
// [...]
_fab=root.FindViewById(…);
_制造。点击+=((发送方,v)=>TestAsync(“制造”);
// [...]
}
专用异步void TestAsync(字符串源)
{
//通过不呼叫wait,您可以告诉代码您不需要这个
//调用方法以等待返回值。
//使用Task.Run显式请求另一个线程处理此请求
任务运行(长任务);
}
专用异步任务
{
而(true){}//线程应该挂在这里
}
任务二:网络
public async Task<int> Network(string s)
{
URL url = new URL("http://www.randomtext.me/api/");
Java.IO.BufferedReader reader = new Java.IO.BufferedReader(new Java.IO.InputStreamReader(url.OpenStream()));
int count = 0;
string str;
while ((str = reader.ReadLine()) != null) {
count += str.Length;
}
reader.Close();
await Task.Delay(3000); // To make sure this method is compiled as async even though it isn't necessary
return count;
}
公共异步任务网络(字符串s)
{
URL=新URL(“http://www.randomtext.me/api/");
Java.IO.BufferedReader reader=new Java.IO.BufferedReader(new Java.IO.InputStreamReader(url.OpenStream());
整数计数=0;
字符串str;
而((str=reader.ReadLine())!=null){
计数+=长度;
}
reader.Close();
wait Task.Delay(3000);//确保此方法编译为异步方法,即使它不是必需的
返回计数;
}
说明:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
// By not calling await you tell the code that you don't need this
// calling method to await a return value.
// using Task.Run explicitly requests another thread process this request
Task.Run(LongTask);
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
与之前一样,这在很大程度上取决于任务的启动方式,请参阅Microsoft文档中的以下引用:
async和await关键字不会导致添加额外的线程
创建。异步方法不需要多线程,因为异步
方法不在自己的线程上运行。该方法在当前服务器上运行
同步上下文,并且仅当
方法处于活动状态。您可以使用Task.Run将CPU绑定的工作移动到
后台线程,但后台线程对进程没有帮助
那只是等待结果出来
我希望这个答案能在回答你的问题时增加一些细节。任务一:异步/等待
private async void TestAsync(string origin)
{
await LongTask();
}
说明:
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
// [...]
_fab = root.FindViewById<FloatingActionButton>(...);
_fab.Click += ((sender, v) => TestAsync("fab"));
// [...]
}
private async void TestAsync(string origin)
{
// By not calling await you tell the code that you don't need this
// calling method to await a return value.
// using Task.Run explicitly requests another thread process this request
Task.Run(LongTask);
}
private async Task LongTask()
{
while (true) { } // Thread should hung here
}
当按钮按下时