【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 ...
随机推荐
- php多路复用(多线程)socket相关应用
最近研究php多线程的问题,发现中文资源少的可怜,仅有的几篇文章被转了又转,但文中内容价值有限.搜索过程中发现国外很多网站引用的一篇文章写的不错,所以翻译过来. 版权声明:可以任意转载,转载时请务必以 ...
- Memory Models And Namespaces
分开编译 不要把变量和函数的定义放到头文件中. 可以分开编译源文件,然后将它们连接起来生成最终的可执行文件. 如果你只修改了一个文件,你可以只重新编译这个文件,之前编译过的其他文件就不需要再次编译了, ...
- Spring WebSocket教程(一)
学习背景 很久以前就知道WebSocket,但那时不论是浏览器还是开发技术对它的支持都还很少.但是,Spring4突然发布,让我眼前一亮,Spring4直接支持WebSocket. 对于Spring我 ...
- Selenium (2) —— Selenium WebDriver + Grid2(101 Tutorial)
Selenium (2) -- Selenium WebDriver + Grid2(101 Tutorial) jvm版本: 1.8.0_65 selenium版本: v2.48.0 (Standa ...
- python出现UnicodeEncodeError有可能产生的另一个原因
在使用python中,我们都有可能遇到如下的错误: UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-2: ...
- centos 7 升级/安装 git 2.7.3
1.安装所需软件包 # yum install curl-devel expat-devel gettext-devel openssl-devel zlib-devel # yum instal ...
- tabs 标签样式
http://www.jq22.com/jquery-info17973 http://www.jq22.com/demo/elementTab201801262311/ 插件描述:基于element ...
- Graph-DFS-图的深度优先遍历
#include <iostream> using namespace std; /* 5 5 1 2 1 3 1 5 2 4 3 5 1 2 4 3 5 ---------------- ...
- php curl_multi系列函数实现多线程抓取网页
最近几天在做一个多搜索引擎关键字排名查询工具,用于及时方便的了解关键词在各大搜索引擎的排名. 在抓取360搜索的时候,发现360搜索每页只支持显示10个搜索结果,如果想获取100个搜索结果数据,就得搜 ...
- Excel查看某列的重复值
例如: 当查看的是B列的重复值时:=IF(COUNTIF(B:B,B1)>1,"重复","")