C# 在C中等待异步任务方法#

C# 在C中等待异步任务方法#,c#,asynchronous,async-await,task,C#,Asynchronous,Async Await,Task,我花了数小时——如果不是几天的话——在以下看似简单的问题上 我正在开发一个Xamarin应用程序,它通过调用Web服务来使用后端数据。下载后,它还会将这些数据存储在内部SQLite数据库中,以避免不必要的webservice调用。数据在第一个应用程序启动时下载一次,然后仅在后端数据已更新的情况下更新 假设我有一个存储库,它将通过调用webservice从后端(异步)加载数据,或者(同步)从内部SQLite数据库加载数据。存储库负责交付数据,而不管数据来自何处。存储库将数据的对象引用存储在可公开访

我花了数小时——如果不是几天的话——在以下看似简单的问题上

我正在开发一个Xamarin应用程序,它通过调用Web服务来使用后端数据。下载后,它还会将这些数据存储在内部SQLite数据库中,以避免不必要的webservice调用。数据在第一个应用程序启动时下载一次,然后仅在后端数据已更新的情况下更新

假设我有一个存储库,它将通过调用webservice从后端(异步)加载数据,或者(同步)从内部SQLite数据库加载数据。存储库负责交付数据,而不管数据来自何处。存储库将数据的对象引用存储在可公开访问的内部列表中。存储库是一个泛型抽象类,它仅由实现类进行子类化,以提供有关类型的信息。与后端同步的所有逻辑都封装在存储库中(据我所知,这是存储库模式)

构建存储库后,通过调用Load()-方法加载它。此方法是异步的,因为它执行以下操作:

  • 获取后端最后一次修改的日期。此操作仅在应用程序启动后执行。上次修改日期存储为属性
  • 通过调用
    GetAll()
    -方法存储数据的对象引用。此方法被标记为async,可以是异步的,也可以是同步的,这取决于数据从何处加载(请参见下面的代码)
    • 如果数据过时,则首先通过调用Web服务下载最新的数据。然后,下载的数据存储在内部SQLite数据库中,替换以前下载的所有数据
    • 下载数据(如果有的话)后,
      GetAll()
      -方法通过查询SQLite数据库返回数据。这是SQLite.NET-Package提供的同步调用
以下行为不起作用(我不理解):

  • 第一次加载存储库时(即
    NeedsUpdate
    返回
    true
    ),一切正常。到目前为止一切正常
  • 在所有后续调用(=应用程序启动)中,加载存储库会导致
    系统.NullReferenceException
    异常。调试代码表明,
    Refresh()
    -方法确实不是从
    GetAll()
    调用的(=预期行为)
我知道你不应该使用async void方法,标记为async的方法应该总是返回一个任务。显然,在我的代码中,后一种情况不是这样的。那么我如何才能使它工作呢

这是我的密码:

BasViewModel.cs(调用存储库上的Load())
公共抽象类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