博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【WP8】同步执行异步代码
阅读量:5226 次
发布时间:2019-06-14

本文共 4870 字,大约阅读时间需要 16 分钟。

微软的StorageFile只支持异步的方式进行文件操作,我之前也封装过一个StorageHelper,但是当所有的方法都是异步的时候也带来一些问题

  1、比如我们不能在构造函数调用异步代码(等待),

  2、比如我们在离开App的时候我们需要对数据进行快速的保存(在事件中),这个时候就不适合用异步了,异步可能会导致保存失败,因为App已经不在前台了

最近就遇到了一个这样的需求

  我封装了一个SqliteHelper类,提供了一些数据库操作的一些常用方法,在数据库使用之前,需要保证数据库路径的文件夹是存在的,如果不能存在,则会抛出异常,所以在SqliteHelper的构造函数判断该文件夹是否存在,如果不存在,则创建该文件夹,但是StorageHelper不支持同步方法(这里不使用IsolatedStorage),我们需要保证在StorageHelper在构造完成时,保证文件夹存在

public SqliteHelper(string dbPath)    {        this.dbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, dbPath);        var directory = Path.GetDirectoryName(dbPath);        if (directory != null)        {            //TODO:构造函数不支持await关键字            //await StorageHelper.Instance.CreateDirectoryAsync(directory);        }    }

  满足上面需求可以有两个方法:

  1、通过一个静态异步方法来构造SqliteHelper的实例,把异步操作放到异步方法里面,但是这种方法会导致不能使用依赖注入IoC

private SqliteHelper(string dbPath)    {        this.dbPath = Path.Combine(ApplicationData.Current.LocalFolder.Path, dbPath);    }    public static async Task
GetSqliteHelper(string dbPath) { var sqliteHelper = new SqliteHelper(dbPath); var directory = Path.GetDirectoryName(dbPath); if (directory != null) {
await StorageHelper.Instance.CreateDirectoryAsync(directory); } return sqliteHelper; }

 

  2、让异步方法同步执行

    我们首先定义一个异步执行Helper,提供异步方法的同步(摘自后面的参考文章)

using System;using System.Collections.Generic;using System.Threading;using System.Threading.Tasks;namespace TestDemo{    public static class AsyncInline    {        public static void Run(Func
item) { var oldContext = SynchronizationContext.Current; var synch = new ExclusiveSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(synch); synch.Post(async _ => { try { await item(); } catch (Exception e) { synch.InnerException = e; throw; } finally { synch.EndMessageLoop(); } }, null); synch.BeginMessageLoop(); SynchronizationContext.SetSynchronizationContext(oldContext); } public static T Run
(Func
> item) { var oldContext = SynchronizationContext.Current; var synch = new ExclusiveSynchronizationContext(); SynchronizationContext.SetSynchronizationContext(synch); T ret = default(T); synch.Post(async _ => { try { ret = await item(); } catch (Exception e) { synch.InnerException = e; throw; } finally { synch.EndMessageLoop(); } }, null); synch.BeginMessageLoop(); SynchronizationContext.SetSynchronizationContext(oldContext); return ret; } private class ExclusiveSynchronizationContext : SynchronizationContext { private bool done; public Exception InnerException { get; set; } readonly AutoResetEvent workItemsWaiting = new AutoResetEvent(false); readonly Queue
> items = new Queue
>(); public override void Send(SendOrPostCallback d, object state) { throw new NotSupportedException("We cannot send to our same thread"); } public override void Post(SendOrPostCallback d, object state) { lock (items) { items.Enqueue(Tuple.Create(d, state)); } workItemsWaiting.Set(); } public void EndMessageLoop() { Post(_ => done = true, null); } public void BeginMessageLoop() { while (!done) { Tuple
task = null; lock (items) { if (items.Count > 0) { task = items.Dequeue(); } } if (task != null) { task.Item1(task.Item2); if (InnerException != null) // the method threw an exeption { throw new AggregateException("AsyncInline.Run method threw an exception.", InnerException); } } else { workItemsWaiting.WaitOne(); } } } public override SynchronizationContext CreateCopy() { return this; } } }}

    接下来我们就可以像同步方法一样使用异步方法了

public class TestClass    {        public int Id { get; set; }        public TestClass()        {            //这里调用一个异步方法,等待异步方法执行返回            Id = AsyncInline.Run(GetIdAsync);            //不支持await            //await GetIdAsync();        }        ///         /// 异步方法        ///         public async Task
GetIdAsync() { //TODO:这里执行模拟自定义操作 await Task.Delay(1000); return 10; } }

 

 

参考文章:

  

  

 

个人能力有限,如果有更好的实现,可以给我留言

转载请注明出处:

 

转载于:https://www.cnblogs.com/bomo/p/3945761.html

你可能感兴趣的文章
Ubuntu14.04+eclipse下cocos2d-x3.0正式版环境的搭建
查看>>
iOS UIScrollView的嵌套使用(仿穷游主界面的实现)
查看>>
mac 如何显示隐藏文件和.点开头文件?
查看>>
AddChildViewController
查看>>
C#解压或压缩文件夹
查看>>
人机猜拳
查看>>
WEB应用从服务器主动推送Data到客户端有那些方式?
查看>>
07 装饰器及进阶
查看>>
黑马程序员——java学习7(152-165)——String类和StringBuffer,StringBuilder
查看>>
Asp.Net 5
查看>>
流式计算之Storm简介
查看>>
44.纯 CSS 创作背景色块变换的按钮特效
查看>>
TopCoder SRM 571 题解
查看>>
CentOS 6.2 安装chromium,并可以使用yum update保持更新
查看>>
vue.js计算属性 vs methods
查看>>
Day004课程内容
查看>>
调整显示屏幕偏移和刷新频率[zt]
查看>>
There are no accidents.
查看>>
图片与文本的对齐方式
查看>>
ABAP 仓库理货单导出
查看>>