【WP8】同步执行异步代码
微软的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<SqliteHelper> 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<Task> 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<T>(Func<Task<T>> 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<Tuple<SendOrPostCallback, object>> items =
new Queue<Tuple<SendOrPostCallback, object>>(); 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<SendOrPostCallback, object> task = null;
lock (items)
{
if (items.Count > )
{
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();
} /// <summary>
/// 异步方法
/// </summary>
public async Task<int> GetIdAsync()
{
//TODO:这里执行模拟自定义操作
await Task.Delay(); return ;
}
}
参考文章:
http://stackoverflow.com/questions/8145479/can-constructors-be-async
个人能力有限,如果有更好的实现,可以给我留言
转载请注明出处:http://www.cnblogs.com/bomo/p/3945761.html
【WP8】同步执行异步代码的更多相关文章
- .NET Core学习笔记(4)——谨慎混合同步和异步代码
原则上我们应该避免编写混合同步和异步的代码,这其中最大的问题就是很容易出现死锁.让我们来看下面的例子: private void ButtonDelayBlock_Click(object sende ...
- Combine 框架,从0到1 —— 4.在 Combine 中执行异步代码
本文首发于 Ficow Shen's Blog,原文地址: Combine 框架,从0到1 -- 4.在 Combine 中执行异步代码. 内容概览 前言 用 Future 取代回调闭包 用输出类型( ...
- redux本来是同步的为什么它能执行异步代码(chunk)实现原理是什么 中间件的实现原理是什么
我们用redux执行同步的时候,都是先发起一个dispatch(actionCreator()) 1.先在actionCreator()中生成一个action对象. 2.由dispatch方法将act ...
- 使用Async同步执行异步函数
为了适应异步编程,减少回调的嵌套,我在项目中引入了Async,当批量处理且需要同步执行一些逻辑相同的异步函数时,觉得还是Async最为靠谱. 我有一个类似下面代码的场景,依据数组中的每一个元素执行一个 ...
- iOS gcd 串行,并行,同步,异步代码研究
参考文章: p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 13.0px Menlo; color: #527eff } span.s1 { } http: ...
- node.js的作用、回调、同步异步代码、事件循环
http://www.nodeclass.com/articles/39274 一.node.js的作用 I/O的意义,(I/O是输入/输出的简写,如:键盘敲入文本,输入,屏幕上看到文本显示输出.鼠标 ...
- ajax同步、异步执行简单理解与证明
此理解范例代码来自前几篇随笔! 首先我们来先了解下AJAX: Ajax:全称“Asynchronous Javascript and XML”(异步Javascript和XML),他是由Javascr ...
- C#完整的通信代码(点对点,点对多,同步,异步,UDP,TCP)
C# code namespace UDPServer { class Program { static void Main(string[] args) { int recv; byte[] dat ...
- IOS多线程知识总结/队列概念/GCD/主队列/并行队列/全局队列/主队列/串行队列/同步任务/异步任务区别(附代码)
进程:正在进行中的程序被称为进程,负责程序运行的内存分配;每一个进程都有自己独立的虚拟内存空间 线程:线程是进程中一个独立的执行路径(控制单元);一个进程中至少包含一条线程,即主线程 队列 dispa ...
随机推荐
- node.js官方文档chm电子书的制作
制作软件:WebCHMSetup2.22.zip,http://www.onlinedown.net/soft/31553.htm 制作好的电子书:Node.js(v6.10.2).zip 参考链接: ...
- Git CMD连接,管理(remote,add,commit,push)github repository
git initmd testcd testgit statusgit add test //git add test/a.txtgit status git remote add origin g ...
- Domain应用之 根据某个Many2one的对象的 X2many对象 过滤
如果两者都是many2one类型的对象,过滤非常简单,在xml中添加domain过滤即可,比如 国家.省市之间的联动关系. 如果想要根据某个对象的X2many类型的字段进行过滤该如何去做呢? 答案是利 ...
- Linxu磁盘分区
http://vbird.dic.ksu.edu.tw/linux_basic/0130designlinux.php#hardware_know(好文章) http://blog.chinaunix ...
- Java编程的逻辑 (41) - 剖析HashSet
本系列文章经补充和完善,已修订整理成书<Java编程的逻辑>,由机械工业出版社华章分社出版,于2018年1月上市热销,读者好评如潮!各大网店和书店有售,欢迎购买,京东自营链接:http:/ ...
- 有赞MySQL自动化运维之路—ZanDB
有赞MySQL自动化运维之路—ZanDB 一.前言 在互联网时代,业务规模常常出现爆发式的增长.快速的实例交付,数据库优化以及备份管理等任务都对DBA产生了更高的要求,单纯的凭借记忆力去管理那几十 ...
- SpringCloud 详解配置刷新的原理 使用jasypt自动加解密后 无法使用 springcloud 中的自动刷新/refresh功能
之所以会查找这篇文章,是因为要解决这样一个问题: 当我使用了jasypt进行配置文件加解密后,如果再使用refresh 去刷新配置,则自动加解密会失效. 原因分析:刷新不是我之前想象的直接调用conf ...
- PCL点云配准(2)
(1)正态分布变换进行配准(normal Distributions Transform) 介绍关于如何使用正态分布算法来确定两个大型点云之间的刚体变换,正态分布变换算法是一个配准算法,它应用于三维点 ...
- Android 自定义倒计时控件CountdownTextView
效果如下: 剩余 00:59:21 package com.bihu.advertiserapp.widgets; import android.annotation.TargetApi; impor ...
- [kafka] 002_kafka_相关术语详细解析
参考: http://www.cnblogs.com/likehua/p/3999538.html http://kafka.apache.org/documentation.html#getting ...