C# 在C中等待异步任务方法#
我花了数小时——如果不是几天的话——在以下看似简单的问题上 我正在开发一个Xamarin应用程序,它通过调用Web服务来使用后端数据。下载后,它还会将这些数据存储在内部SQLite数据库中,以避免不必要的webservice调用。数据在第一个应用程序启动时下载一次,然后仅在后端数据已更新的情况下更新 假设我有一个存储库,它将通过调用webservice从后端(异步)加载数据,或者(同步)从内部SQLite数据库加载数据。存储库负责交付数据,而不管数据来自何处。存储库将数据的对象引用存储在可公开访问的内部列表中。存储库是一个泛型抽象类,它仅由实现类进行子类化,以提供有关类型的信息。与后端同步的所有逻辑都封装在存储库中(据我所知,这是存储库模式) 构建存储库后,通过调用Load()-方法加载它。此方法是异步的,因为它执行以下操作:C# 在C中等待异步任务方法#,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,我花了数小时——如果不是几天的话——在以下看似简单的问题上 我正在开发一个Xamarin应用程序,它通过调用Web服务来使用后端数据。下载后,它还会将这些数据存储在内部SQLite数据库中,以避免不必要的webservice调用。数据在第一个应用程序启动时下载一次,然后仅在后端数据已更新的情况下更新 假设我有一个存储库,它将通过调用webservice从后端(异步)加载数据,或者(同步)从内部SQLite数据库加载数据。存储库负责交付数据,而不管数据来自何处。存储库将数据的对象引用存储在可公开访
- 获取后端最后一次修改的日期。此操作仅在应用程序启动后执行。上次修改日期存储为属性
- 通过调用
-方法存储数据的对象引用。此方法被标记为async,可以是异步的,也可以是同步的,这取决于数据从何处加载(请参见下面的代码)GetAll()
- 如果数据过时,则首先通过调用Web服务下载最新的数据。然后,下载的数据存储在内部SQLite数据库中,替换以前下载的所有数据
- 下载数据(如果有的话)后,
-方法通过查询SQLite数据库返回数据。这是SQLite.NET-Package提供的同步调用GetAll()
- 第一次加载存储库时(即
返回NeedsUpdate
),一切正常。到目前为止一切正常true
- 在所有后续调用(=应用程序启动)中,加载存储库会导致
异常。调试代码表明,系统.NullReferenceException
-方法确实不是从Refresh()
调用的(=预期行为)GetAll()
公共抽象类BaseViewModel:MvxViewModel
{
受保护的电子存储库;
公共虚拟异步任务Init()
{
if(存储库!=null)
{
等待Repository.Load();
}
}
}
Repository.cs
公共抽象类存储库:IRepository
受保护列表项列表=新列表();
公共清单项目
{
获取{return ItemList;}
设置
{
ItemList=值;
如果(ItemsChanged!=null)
项目列表(此,项目列表);
}
}
公共虚拟异步任务加载()
{
if(CurrentUpdate.Equals(DateTime.MaxValue)| | CurrentUpdate.Equals(DateTime.MinValue))
CurrentUpdate=Wait WebService.Status(异常=>{});
Items=wait GetAll();
}
公共虚拟异步任务GetAll()
{
如果(需要更新日期)
等待刷新();
返回DbService.All();
}
公共异步任务刷新()
{
var result=wait WebService.DoGet(错误=>{});
如果(ItemsDownloaded!=null)
ItemsDownloaded(此,结果);
重新加载数据库(结果);
}
受保护的void重载数据库(IEnumerable items)
{
DbService.DeleteAll();
foreach(项目中的var项目)
{
DbService.Insert(项目);
}
LastUpdate=DateTime.Now;
FileService.WriteFile(文件名,LastUpdate.ToString());
}
}
DatabaseService.cs
公共抽象类数据库服务{
公共列表全部()
{
//ISQLiteConnection在之前已实例化
返回连接.Table().ToList();
}
}
WebService.cs
公共抽象类WebService
公共虚拟异步任务数据集(操作错误)
{
使用(var client=new HttpClient())
{
字符串结果=等待客户端。GetStringAsync(“http://example.com/myApi");
返回JsonConvert.DeserializeObject(结果);
}
}
}
堆栈跟踪
06-17 14:21:43.701 D/AndroidRuntime(2897):关闭虚拟机
线程“未知”(0x4)已退出,代码为0(0x0)。
发生未处理的异常。
06-17 14:21:45.760 E/AndroidRuntime(2897):致命异常:主
06-17 14:21:45.760E/AndroidRuntime(2897):过程:ch.bbv.fumetto,PID:2897
06-17 14:21:45.760E/AndroidRuntime(2897):java.lang.RuntimeException:java.lang.reflect.InvocationTargetException
06-17 14:21:45.760e/AndroidRuntime(2897):在com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
06-17 14:21:45.760E/AndroidRuntime(2897):由以下原因引起:java.lang.reflect.InvocationTargetException
06-17 14:21:45.760E/AndroidRuntime(2897):位于java.lang.reflect.Method.invoke(本机方法)
06-17 14:21:45.760e/AndroidRuntime(2897):在java.lang.reflect.Method.invoke(Method.java:372)
06-17 14:21:45.760e/AndroidRuntime(2897):在com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
06-17 14:21:45.760 E/AndroidRuntime(2897):…还有一个
06-17 14:21:45.760E/AndroidRuntime(2897):由以下原因引起:
public abstract class BaseViewModel<T> : MvxViewModel
{
protected IRepository<T> Repository;
public virtual async Task Init()
{
if (Repository != null)
{
await Repository.Load();
}
}
}
public abstract class Repository<T> : IRepository<T>
protected List<T> ItemList = new List<T>();
public List<T> Items
{
get { return ItemList; }
set
{
ItemList = value;
if (ItemsChanged != null)
ItemsChanged(this, ItemList);
}
}
public virtual async Task Load()
{
if (CurrentUpdate.Equals(DateTime.MaxValue) || CurrentUpdate.Equals(DateTime.MinValue))
CurrentUpdate = await WebService.Status(exception => { });
Items = await GetAll();
}
public virtual async Task<List<T>> GetAll()
{
if (NeedsUpdate)
await Refresh();
return DbService.All();
}
public async Task Refresh()
{
var result = await WebService.DoGet(error => { });
if (ItemsDownloaded != null)
ItemsDownloaded(this, result);
ReloadDatabase(result);
}
protected void ReloadDatabase(IEnumerable<T> items)
{
DbService.DeleteAll();
foreach (var item in items)
{
DbService.Insert(item);
}
LastUpdate = DateTime.Now;
FileService.WriteFile(FileName, LastUpdate.ToString());
}
}
public abstract class DatabaseService<T> {
public List<T> All()
{
// ISQLiteConnection was instantiated before
return Connection.Table<T>().ToList();
}
}
public abstract class WebService<T>
public virtual async Task<List<T>> DoGet(Action<Exception> error)
{
using (var client = new HttpClient())
{
string result = await client.GetStringAsync("http://example.com/myApi");
return JsonConvert.DeserializeObject<T>(result);
}
}
}
06-17 14:21:43.701 D/AndroidRuntime( 2897): Shutting down VM
The thread 'Unknown' (0x4) has exited with code 0 (0x0).
An unhandled exception occured.
06-17 14:21:45.760 E/AndroidRuntime( 2897): FATAL EXCEPTION: main
06-17 14:21:45.760 E/AndroidRuntime( 2897): Process: ch.bbv.fumetto, PID: 2897
06-17 14:21:45.760 E/AndroidRuntime( 2897): java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
06-17 14:21:45.760 E/AndroidRuntime( 2897): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
06-17 14:21:45.760 E/AndroidRuntime( 2897): Caused by: java.lang.reflect.InvocationTargetException
06-17 14:21:45.760 E/AndroidRuntime( 2897): at java.lang.reflect.Method.invoke(Native Method)
06-17 14:21:45.760 E/AndroidRuntime( 2897): at java.lang.reflect.Method.invoke(Method.java:372)
06-17 14:21:45.760 E/AndroidRuntime( 2897): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
06-17 14:21:45.760 E/AndroidRuntime( 2897): ... 1 more
06-17 14:21:45.760 E/AndroidRuntime( 2897): Caused by: md52ce486a14f4bcd95899665e9d932190b.JavaProxyThrowable: System.NullReferenceException: Object reference not set to an instance of an object
06-17 14:21:45.760 E/AndroidRuntime( 2897): at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw () <IL 0x00011, 0x0004b>
06-17 14:21:45.760 E/AndroidRuntime( 2897): at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>m__0 (object) <IL 0x00006, 0x0003b>
06-17 14:21:45.760 E/AndroidRuntime( 2897): at Android.App.SyncContext/<Post>c__AnonStorey0.<>m__0 () [0x00000] in /Users/builder/data/lanes/monodroid-mavericks-monodroid-5.1-series/d419c934/source/monodroid/src/Mono.Android/src/Android.App/SyncContext.cs:18
06-17 14:21:45.760 E/AndroidRuntime( 2897): at Java.Lang.Thread/RunnableImplementor.Run () [0x0000b] in /Users/builder/data/lanes/monodroid-mavericks-monodroid-5.1-series/d419c934/source/monodroid/src/Mono.Android/src/Java.Lang/Thread.cs:36
06-17 14:21:45.760 E/AndroidRuntime( 2897): at Java.Lang.IRunnableInvoker.n_Run (intptr,intptr) [0x00009] in /Users/builder/data/lanes/monodroid-mavericks-monodroid-5.1-series/d419c934/source/monodroid/src/Mono.Android/platforms/android-21/src/generated/Java.Lang.IRunnable.cs:71
06-17 14:21:45.760 E/AndroidRuntime( 2897): at (wrapper dynamic-method) object.5b2f2ea1-978e-4306-9701-97a7ac2d86c0 (intptr,intptr) <IL 0x00011, 0x0001f>
06-17 14:21:45.760 E/AndroidRuntime( 2897):
06-17 14:21:45.760 E/AndroidRuntime( 2897): at mono.java.lang.RunnableImplementor.n_run(Native Method)
06-17 14:21:45.760 E/AndroidRuntime( 2897): at mono.java.lang.RunnableImplementor.run(RunnableImplementor.java:29)
06-17 14:21:45.760 E/AndroidRuntime( 2897): at android.os.Handler.handleCallback(Handler.java:739)
06-17 14:21:45.760 E/AndroidRuntime( 2897): at android.os.Handler.dispatchMessage(Handler.java:95)
06-17 14:21:45.760 E/AndroidRuntime( 2897): at android.os.Looper.loop(Looper.java:135)
06-17 14:21:45.760 E/AndroidRuntime( 2897): at android.app.ActivityThread.main(ActivityThread.java:5257)
06-17 14:21:45.760 E/AndroidRuntime( 2897): ... 4 more
06-17 14:21:49.772 I/Process ( 2897): Sending signal. PID: 2897 SIG: 9