[英]Any event raised after an async function does not update UI properly
我正在尝试向我的应用程序添加一个基本的回调,以便随着应用程序通过更新任务的进行,加载状态标签也会更新。 但是由于某种原因,在调用一个特定的异步方法之后,此后引发的任何事件都不会更新UI。
我尝试了各种configure await设置,并通过async方法本身进行了查看,但找不到任何明显错误的东西。
public async Task RefreshTable<T>() where T : class, IEntity
{
try
{
OnContentUpdateProgressChange(this, new MessageEventArgs($"RefreshTable before {typeof(T).Name}"));
var tableJsonData = await ApiService.GetEntityListAsync<T>();
OnContentUpdateProgressChange(this, new MessageEventArgs($"RefreshTable after {typeof(T).Name}"));
await LoadTableData(Set<T>(), tableJsonData);
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
}
public async Task<List<T>> GetEntityListAsync<T>(string url = null) where T : class
{
if (string.IsNullOrEmpty(url))
{
url = typeof(T).Name.Replace("_", "");
}
try
{
string entityList = null;
HttpResponseMessage response = await Client.GetAsync(url);
if (response.IsSuccessStatusCode)
{
entityList = await response.Content.ReadAsStringAsync();
var backupFile = Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.Personal), typeof(T).Name);
using (var writer = File.CreateText(backupFile))
{
await writer.WriteLineAsync(entityList.ToString());
}
}
return await Task.Factory.StartNew(() => JsonConvert.DeserializeObject<List<T>>(entityList));
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
throw;
}
}
private void DB_OnContentUpdateProgressChange(object sender, library.EventArguments.MessageEventArgs e)
{
lblLoadingState.Text = e.Message;
}
在调用GetEntityListAsync之前引发的事件成功更新了UI,但是之后没有。
从我的理解中可以看出,这是一个UI线程问题当您在背景线程中进行一些更改时,异步方法始终建议您对UI进行更改,这些更改将影响UI。 MainThread
或UIThread
。 现在,您需要做的非常简单。 每当您做出应该以任何形式影响UI的更改时,都应在UI线程上进行更改。
我想做的是在一个方法中对所有UI进行更改,然后我希望拥有一个Activity类的基础版本,该基类具有帮助者,让我检查它是否为MainThread并相应地使用该方法进行更改。
添加从AppCompatActivity继承的Activity,然后向其添加以下内容。
public abstract class BaseActivity : AppCompatActivity { protected override void OnCreate(Bundle savedInstanceState) { base.OnCreate(savedInstanceState); } public bool IsMainThread => Build.VERSION.SdkInt >= BuildVersionCodes.M ? Looper.MainLooper.IsCurrentThread : Looper.MyLooper() == Looper.MainLooper; public void RunOnMainThread(Action action) { if (IsMainThread) action(); else RunOnUiThread(action); } }
然后进行UI更改,例如:
RunOnMainThread(() => { LabelDoSomething.Text = "New Text"; });
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.