• 766 阅读
  • 10 回复

asp.net ashx(使用Nito.AsyncEx) 一般处理程序 使用async await异步直接 copy可用哦

视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)
以前一直很懒  碰到ashx要用await异步就绕开  用aspx  或者mvc异步控制器  这次公司需要  我查了国内的文章基本都不能简单copy来处理一堆错关键的过程中函数BeginProcessRequest和endxxx的代码是缺失的  结果我去stackoverflow.com查,才找到一段内容,贴在这里 以备自己后用 也希望之后能帮助喜欢搜索解决问题 的大家。
关键其实就在Nito.AsyncEx这个库  nuget可以下载到  有3个dll,是异步 的一些封装,顺便吐槽一下  到现在很多人还不习惯用nuget 真不知道是我大天朝网络神盾太厉害,还是这些位。。。。算了不说了 呵呵

代码 复制 - 运行

 /// <summary>
    /// HttpAsyncHandlerTestAsync 的摘要说明
    /// </summary>
    public class _002 : HttpAsyncHandlerBase
    {
        /// <summary>
        /// 需要HttpAsyncHandlerBase类
        /// 需要Nito.AsyncEx、Nito.AsyncEx.Concurrent、Nito.AsyncEx.Enlightenment相关dll
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public override async Task ProcessRequestAsync(HttpContext context)
        {
            context.Response.ContentType = "text/html";
            for (int i = 1; i < 10; i++)
            {
                //传递context 只是模拟一下传参
                string data = null;
                try
                {
                    data = await DoSomething(1);
                }
                catch (Exception oe) { data = oe.Message + oe.StackTrace; }
                context.Response.Write(data);
                context.Response.Flush();
                await Task.Delay(TimeSpan.FromSeconds(2));
            }
        }

        public async Task<string> DoSomething(int x = 0)
        {

            //调用Delay 只是为了找个地方await 正常情况这里应该是await一个io行为
            await Task.Delay(0);

            return (1 / x).ToString();
        }
    }


    
    public abstract class HttpAsyncHandlerBase : IHttpAsyncHandler
    {
        public abstract Task ProcessRequestAsync(HttpContext context);

        public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
        {
            var task = ProcessRequestAsync(context);
            return Nito.AsyncEx.AsyncFactory.ToBegin(task, cb, extraData);
        }

        public void EndProcessRequest(IAsyncResult result)
        {
            Nito.AsyncEx.AsyncFactory.ToEnd(result);
        }

        public void ProcessRequest(HttpContext context)
        {
            EndProcessRequest(BeginProcessRequest(context, null, null));
        }

        public virtual bool IsReusable
        {
            get { return true; }
        }
    }


Nito.AsyncEx.4.0.1.rar (您是游客您没有权限下载)


本帖最后由 张小鱼 于 2018-01-25 13:40 编辑
小鱼的淘宝店铺-多多支持哇
视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)
https://github.com/StephenCleary/AsyncEx


AsyncEx-master.zip (您是游客您没有权限下载)



源码
小鱼的淘宝店铺-多多支持哇
视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)

代码 复制 - 运行

using Nito.AsyncEx;
using System;
using System.Collections.Concurrent;
using System.Threading.Tasks;

namespace AsyncCollectionDemo
{
    class Program
    {

        private static readonly AsyncCollection<int> _asyncStack = new AsyncCollection<int>(new ConcurrentStack<int>(), maxCount: 1);


        static void Main(string[] args)
        {
            ProducerConsumerDemo();
        }

        private static async void ConsumerThread()
        {
            await Task.Run(async () =>
             {
                 //Consumer code 
                 while (await _asyncStack.OutputAvailableAsync())
                 {
                     Console.WriteLine(await _asyncStack.TakeAsync());
                     //Thread.Sleep(1000);
                 }
             });
        }

        private static async void ProducerConsumerDemo()
        {
            ConsumerThread();
            //Producer code 
            await _asyncStack.AddAsync(7);
            await _asyncStack.AddAsync(13);
            await _asyncStack.AddAsync(19);
            _asyncStack.CompleteAdding();


            Console.WriteLine("Press any key to continue ..");
            Console.ReadKey(); 
        }

    }
}



http://toreaurstad.blogspot.co.uk/2016/06/high-performance-producer-consumer.html
本帖最后由 张小鱼 于 2018-01-25 13:40 编辑
小鱼的淘宝店铺-多多支持哇
视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)
异步类写法、本文是连接SQLLIT数据库的:


So just to rephrase: Don’t make your Application lifetime events async void!
Yes, I learned the hard way. Yes I’ve read, and know, about the: Never make a void async. But if you want write an event-handler you’ve got no choice. But beware, sometimes things look to be working okay, but actually don’t.
Alright, back to where all my trouble started. Every Windows Phone App developer knows about the Application Lifetime events that are automatically subscribed to in the App.xaml.cs. You’ve probably added code to at least one of the following event-handlers.
Application_Launching: Occurs when the application is being launched
Application_Closing: Occurs when the application is exiting
Application_Activated: Occurs when the application is being made active after previously being put into a dormant state or tombstoned.
Application_Deactivated: Occurs when the application is being deactivated. You have 10 seconds to complete your work, though it’s recommended to aim for completing the work within 2 seconds.
No await in those event handlers!
Alright, I’m just writing code. I need to perform the last small SQLite query to save some state. Hmm, that’s done in the Closing method. I’m writing the code, oh yeah, the SQLite query is an asynchronous operation. I write await, hmm, mark the method as async void. Hmm, shouldn’t do that, should I? It’s an event-handler, true, but don’t forget you’ve done it before, and the code does execute. Okay move on and test later. I’ll be honest, I forgot to test, but I got some strange issues that I had difficulty with solving.
What I found out, that as soon as the word await was hit in the event-handler, the thread was given back to the application, which kind of signaled the app, I’m ready to terminate. Ouch! The actual never executed, that was painful! Just note, after save the settings in the SQLite database, I did the closing of all open connections. This closing never happened either, which in itself caused strange situations with trying to execute queries on closed connections when the app resumed.
Okay I learned the hard way, don’t use await in the above mentioned event-handlers, better don’t use it in any event-handler.
But I need that API call, which happens to be async
So I started looking for a way to call a Task synchronously. Yes I found a way on StackOverflow that works very well. So I could change my code like this, which indeed does result in nice code I think.


代码 复制 - 运行

private void Application_Closing(object sender, ClosingEventArgs e)
{
    Debug.WriteLine("BEGIN - ApplicationClosing");
    AsyncHelpers.RunSync(() => ApplicationClosingAsync(sender, e));
    Debug.WriteLine("END - ApplicationClosing");
}
 
private async Task ApplicationClosingAsync(object sender, ClosingEventArgs e)
{
    try
    {
        ApplicationSettings settings = await ApplicationSettings.LoadSettings();
        settings.LastAppRun = DateTime.Now;
        await ApplicationSettings.SaveSettings(settings);
        ViewModelLocator.Cleanup();
        SQLiteConnectionPool.Shared.ApplicationSuspended();
    }
    catch (Exception exception)
    {
        //swallow exceptions that occur at this moment.
    }
}



All the code that was originally in the Application_Closing event handler is now moved to the ApplicationClosingAsync method, which indeed is an async method which returns a Task. The method contains multiple await statements, the keyword that shouldn’t be in de event handler itself. I added the Debug information for testing purpose, so you can see everything get’s called. The magic is in the AsyncHelper method which I copied from the StackOverflow site, so please place the credits in the right place. I’ve shown the code for Application_Closing, but it works for the other event-handlers as well.
UPDATE 1: According to Oren Novotny this feature also exists in the Nito.AsyncEx NuGet Package. Pick the one you like best, but at least test your code.

代码 复制 - 运行

public static class AsyncHelpers
{
    /// <summary>
    /// Execute's an async Task method which has a void return value synchronously
    /// </summary>
    /// <param name="task">Task method to execute</param>
    public static void RunSync(Func<Task> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        synch.Post(async _ =>
        {
            try
            {
                await task();
            }
            catch (Exception e)
            {
                synch.InnerException = e;
                throw;
            }
            finally
            {
                synch.EndMessageLoop();
            }
        }, null);
        synch.BeginMessageLoop();
 
        SynchronizationContext.SetSynchronizationContext(oldContext);
    }
 
    /// <summary>
    /// Execute's an async Task<T> method which has a T return type synchronously
    /// </summary>
    /// <typeparam name="T">Return Type</typeparam>
    /// <param name="task">Task<T> method to execute</param>
    /// <returns></returns>
    public static T RunSync<T>(Func<Task<T>> task)
    {
        var oldContext = SynchronizationContext.Current;
        var synch = new ExclusiveSynchronizationContext();
        SynchronizationContext.SetSynchronizationContext(synch);
        T ret = default(T);
        synch.Post(async _ =>
        {
            try
            {
                ret = await task();
            }
            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 > 0)
                    {
                        task = items.Dequeue();
                    }
                }
                if (task != null)
                {
                    task.Item1(task.Item2);
                    if (InnerException != null) // the method threw an exeption
                    {
                        throw new AggregateException("AsyncHelpers.Run method threw an exception.", InnerException);
                    }
                }
                else
                {
                    workItemsWaiting.WaitOne();
                }
            }
        }
 
        public override SynchronizationContext CreateCopy()
        {
            return this;
        }
    }
}



详见:http://mark.mymonster.nl/2013/07/10/donrsquot-make-your-application-lifetime-events-async-void/

本帖最后由 张小鱼 于 2018-01-25 13:53 编辑
小鱼的淘宝店铺-多多支持哇

Web API和动态数据访问

视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)

。 净的岩石 集855杰夫·弗里茨评论ASP。 净Web API有点让人困惑的用途。 我不同意这个说法,但是我想解决他特别是一点:Web API也许只是另一种形式的存储库。
Web API不仅仅是一个存储库中。 是的,它的确是一个协议映射层。 正如鲍勃叔叔曾经指出,一个web前端或api只是一个映射层并不是真正的应用程序。
然而,在许多情况下,一个可以说web-api-as-repository是一个相当坚实的用例。 OData是一个很好的例子。 但是,我在想另一个论点为动态语言我听过:当你只是从网络数据库,你并不是真正的工作类型。
本着这种精神,我着手编写一个简单的Web API使用SQL和JSON,没有明确的类定义。 你可以看到的结果这一要点:


代码 复制 - 运行

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.SqlServerCe;
using System.Diagnostics;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Web.Http;
using Dapper;
using Newtonsoft.Json.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            Nito.AsyncEx.AsyncContext.Run(() => MainAsync(args));
        }

        static async Task MainAsync(string[] args)
        {
            var config = new HttpConfiguration();
            WebApiConfig.Register(config);
            using (var server = new HttpServer(config))
            using (var client = new HttpClient(server))
            {
                client.BaseAddress = new Uri("http://localhost/");
                var cts = new CancellationTokenSource();

                var json = @"{""title"":""Task"",""description"":""The task"",""createdDate"":""" + DateTime.UtcNow.ToString() + "\"}";
                var postRequest = new HttpRequestMessage(HttpMethod.Post, "/api/tasks")
                {
                    Content = new StringContent(json, Encoding.UTF8, "application/json")
                };
                var postResponse = await client.SendAsync(postRequest, cts.Token);
                Trace.Assert(postResponse.StatusCode == HttpStatusCode.Created);

                var location = postResponse.Headers.Location.AbsoluteUri;
                var getResponse = await client.GetAsync(location);
                Trace.Assert(getResponse.StatusCode == HttpStatusCode.OK);

                var getBody = await getResponse.Content.ReadAsAsync<JObject>();
                dynamic data = getBody;
                Trace.Assert((string)data.title == "Task");
            }

            Console.WriteLine("Press any key to quit.");
            Console.ReadLine();
        }
    }

    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

    public class TasksController : ApiController
    {
        static string _connString = ConfigurationManager.ConnectionStrings["Database1"].ConnectionString;
        public async Task<IEnumerable<dynamic>> GetAll()
        {
            using (var connection = new SqlCeConnection(_connString))
            {
                await connection.OpenAsync();

                IEnumerable<dynamic> tasks = await connection.QueryAsync<dynamic>("select Id as id, Title as title, Description as description, CreatedDate as createdDate from Tasks;");
                return tasks;
            }
        }

        public async Task<dynamic> Get(int id)
        {
            using (var connection = new SqlCeConnection(_connString))
            {
                await connection.OpenAsync();

                IEnumerable<dynamic> tasks = await connection.QueryAsync<dynamic>("select Id as id, Title as title, Description as description, CreatedDate as createdDate from Tasks where Id = @id;", new { id = id });
                if (!tasks.Any())
                    throw new HttpResponseException(Request.CreateErrorResponse(HttpStatusCode.NotFound, "Task not found"));
                
                return tasks.First();
            }
        }

        public async Task<HttpResponseMessage> Post(JObject value)
        {
            dynamic data = value;
            IEnumerable<int> result;
            using (var connection = new SqlCeConnection(_connString))
            {
                await connection.OpenAsync();

                connection.Execute(
                    "insert into Tasks (Title, Description, CreatedDate) values (@title, @description, @createdDate);",
                    new
                    {
                        title = (string)data.title,
                        description = (string)data.description,
                        createdDate = DateTime.Parse((string)data.createdDate)
                    }
                );

                result = await connection.QueryAsync<int>("select max(Id) as id from Tasks;");
            }

            int id = result.First();
            data.id = id;
            var response = Request.CreateResponse(HttpStatusCode.Created, (JObject)data);
            response.Headers.Location = new Uri(Url.Link("DefaultApi", new { controller = "Tasks", id = id }));
            return response;
        }
    }
}

我使用衣冠楚楚的为了简化数据访问,尽管我一样可以使用巨大的,PetaPoco,或Simple.Data。 主要是我想使用SQL,因此我和衣冠楚楚的。
我也绑定到模型JObject,我立即赶dynamic。 我使用一个匿名对象提供SQL语句中的参数的值,铸件满足衣冠楚楚的动态对象的字段。
总之,我有点像。 一切都很小,我可以直接使用SQL,这一点不会困扰我。 我有一个类来管理数据访问和API翻译,但每种方法的最终目标仍然是小:通过HTTP检索数据并将其呈现。 这违反了SRP,但我不介意。 上面的代码不是很可测试的,但一个API这样我会更倾向于做顶级测试。 只是不够深,需要大量的非常具体的,低级的测试,恕我直言。
同时,请再次注意,这只是检索数据,推动通过一个API。 这不是火箭科学。 f#类型提供者在SQL会给一个好足够的完整性检查。 为什么要生成一串类型?
引出了另一个点的另一篇文章:我怎么办我需要添加一些逻辑来处理或转换数据检索吗?

作为一个未来的运动,我想看看这将限制与Web API OData扩展。 这可能很有趣。


原文:https://wizardsofsmart.wordpress.com/2013/03/21/web-api-and-dynamic-data-access/
小鱼的淘宝店铺-多多支持哇
小鱼的淘宝店铺-多多支持哇

惰性的异步 - LazyAsync

视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)
惰性的异步


I’ve been moving some data access code to to use Lazy<T> whenever I want to defer actually fetching the data until it’s first needed.  What I’ve always found interesting is there is no Lazy Async.
In the exact use case it’s when an application loads, there is some static data loaded from a database.  This data is the cached for later use.
However, in many situations it’s not actually needed until much later if at all.  Why take the performance hit of fetching the data on app startup if that data is often times not needed?
That’s the whole purpose of Lazy<T>.  But as mentioned, why is there no Lazy Async?  If i want to defer IO, that’s generally async.
Here is more info on Lazy Initialization if it’s new to you.


代码 复制 - 运行

/// <summary>
/// Provides support for asynchronous lazy initialization.
/// </summary>
/// <typeparam name="T"></typeparam>
public class LazyAsync<T> : Lazy<Task<T>>
{
    /// <summary>
    ///  Initializes a new instance of the LazyAsync`1 class. When lazy initialization
    ///  occurs, the specified initialization function is used.
    /// </summary>
    /// <param name="taskFunc">The delegate that is invoked to produce the lazily initialized Task when it is needed.</param>
    public LazyAsync(Func<Task<T>> taskFunc) : 
        base(() => Task.Factory.StartNew(taskFunc).Unwrap()) { }
}



I’ve just created a small class that extends Lazy<T>.  The usage is how you can expect.  Here is a small sample that fetches data from an HTTP service.

代码 复制 - 运行

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Newtonsoft.Json;

namespace LazyAsync
{
    public class LazyAsync<T> : Lazy<Task<T>>
    {
        public LazyAsync(Func<Task<T>> taskFactory) : base(
            () => Task.Factory.StartNew(taskFactory).Unwrap()) { }
    }

    class Program
    {
        public static async Task Main(string[] args)
        {
            var currencyService = new CurrencyService();
            var rates = await currencyService.ExchangeRates.Value;
            var cad = rates.Rates.Single(x => x.Key == "CAD");
            Console.WriteLine($"USD to CAD = {cad.Value}");
            Console.ReadKey();
        }
    }

    public class CurrencyService : IDisposable
    {
        private readonly HttpClient _httpClient;
        public LazyAsync<ExchangeRates> ExchangeRates { get; set; }

        public CurrencyService()
        {
            _httpClient = new HttpClient();
            ExchangeRates = new LazyAsync<ExchangeRates>(async () =>
            {
                var json = await _httpClient.GetStringAsync("http://api.fixer.io/latest?base=USD");
                return JsonConvert.DeserializeObject<ExchangeRates>(json);
            });
        }

        public void Dispose()
        {
            _httpClient?.Dispose();
        }
    }

    public class ExchangeRates
    {
        public string Base { get; set; }
        public DateTime Date { get; set; }
        public Dictionary<string, decimal> Rates { get; set; }
    }
}



Source
All the source code for my demo is available on GitHub if you want to try it yourself.
If anyone has any other suggestions or recommendations about blog topics, please leave comment or let me know on twitter.


RE:========================
本帖最后由 张小鱼 于 2018-01-25 14:09 编辑
小鱼的淘宝店铺-多多支持哇

Will you just wait a minute?! NUnit and Async/Await

视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)
Will you just wait a minute?! NUnit and Async/Await

I was being a good-doobie.  Honest.
I had written a prototype – just something to prove that a particular approach could work.  It did, and so now it was time for me to actually bring that code up to production quality.  Part of that meant modifying how I was invoking the third-party web services – they  needed to be done asynchronously.
So I went through and wrote my unit tests to also run asynchronously:

代码 复制 - 运行

        [Test]
        public async void Divide_4DividedBy2_Equals2()
        {
            AsyncUnitTest.Math MathLibrary = new AsyncUnitTest.Math();

            float Quotient = await MathLibrary.Divide(4, 2);

            Assert.AreEqual(2, (int)Quotient);
        }

I ran it through NUnit on my machine, and everything was peachy-keen.  I ended up writing nearly 50 unit tests* like that, converting over all of my calls.  I committed the code, and let TeamCity take over.
And watched every one of those new tests break.
When I looked at the TeamCity log, the errors seemed to hint that the test runner was simply not waiting for the thing under test to complete before trying to run the asserts.  I started searching for things like "nunit async", and pretty quickly across this two-part series by Stephen Cleary:

In this series, Cleary says that the underlying problem of running async tests is that they don’t have a proper context:
We’ve encountered a situation very similar to async in Console programs: there is no async context provided for unit tests, so they’re just using the thread pool context. This means that when we await our method under test, then our async test method returns to its caller (the unit test framework), and the remainder of the async test method – including the Assert – is scheduled to run on the thread pool. When the unit test framework sees the test method return (without an exception), then it marks the method as “Passed”. Eventually, the Assert will fail on the thread pool.

His solution is to simply give the test an async context, and he provides a very handy wrapper to do just that.  I first had to install his Nito.AsyncEx NuGet package, and then wrap my test in AsyncContext.Run:

代码 复制 - 运行

        [Test]
        public void Divide_4DividedBy2_Equals2_Asynchrofied()
        {
            AsyncContext.Run(async () =>
            {
                AsyncUnitTest.Math MathLibrary = new AsyncUnitTest.Math();

                float Quotient = await MathLibrary.Divide(4, 2);

                Assert.AreEqual(2, (int)Quotient);
            });
        }

Notice that I’ve removed the "async" keyword from the test itself; AsyncContext.Run does all the work here.  After updating and committing my first test using AsyncContext.Run – a test test, if you will – it ran successfully on TeamCity.  I updated the other 48, and finally got a green build.
***
My build was stable again, but Cleary’s explanation didn’t answer the question of why this worked on my machine in the first place – without using his very awesome library – so, I kept digging.
I first looked up exactly what TeamCity was using to run the tests – it was NUnit, the same as what was on my machine, with a minor different in the version.  My local copy was 2.6.2, while the version on the build server was 2.6.1.  Could there be a difference in how 2.6.1 was handling async?
Why yes.  Yes there was.  In the NUnit 2.6.2 release notes I found this:
When running under .NET 4.5, async test methods are now supported. For test cases returning a value, the method must return Task<T>, where T is the type of the returned value. For single tests and test cases not returning a value, the method may return either void or Task.
– Source: http://nunit.org/index.php?p=releaseNotes&r=2.6.2

Are you serious?  I just happen to have the first version of NUnit that would properly handle async on my machine, but the build server was one notch older, and therefore couldn’t?  *facepalm*
To further prove that this was the real source of my issue, I installed NUnit 2.6.1 and 2.6.2 side by side on my machine.  I took my two tests from above, both of which should have tried to execute the MathLibrary.Divide function which included a 2-second delay:
   public class Math    {        public async Task<float> Divide(int Numerator, int Denominator)        {            await Task.Delay(2000);            return Numerator / Denominator;        }    }
When I ran these two tests through NUnit 2.6.1, Divide_4DividedBy2_Equals2 completes in a couple hundredths of a second, while Divide_4DividedBy2_Equals2_Asynchrofied takes just over 2 seconds to complete, for a total of just over 2 seconds:

When I ran these through NUnit 2.6.2, EACH test takes just over 2 seconds to complete, for a total of just over 4 seconds:

So, I have two choices – switch my builds on TeamCity to use at least NUnit 2.6.2 to run the tests, or use Cleary’s Nito.AsyncEx library, which will allow me to leave the build server as is.  In any event, at least I have a reasonable explanation for what was happening.
The funny thing is that it’s usually MSBuild that messes with me.  Apparently NUnit gave him the week off.


* Yes, I realize that by calling the service directly, this no longer counts as a "unit" test, but rather an integration test.  That distinction isn’t relevant to the issue described in this post, though, so I’m going to gloss over the mock objects in the real code.


From:https://markegilbert.wordpress.com/2014/10/23/will-you-just-wait-a-minute-nunit-and-asyncawait/
小鱼的淘宝店铺-多多支持哇

使用Nito.AsyncEx实现异步锁(转)

视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)
使用Nito.AsyncEx实现异步锁(转)

Lock是常用的同步锁,但是我们无法在Lock的内部实现异步调用,比如我们无法使用await.
以下面的代码为例,当你在lock内部使用await时,VS会报错提醒。

最简单的解决办法就是使用第三方的库Nito.AsyncEx。可以通过Nuget安装。

通过AsyncLock就可以在锁的内部实现异步操作了。
样例代码如下:

代码 复制 - 运行

public class AsyncLockDemo
    {
        //private readonly object _mutex = new object();
        private readonly AsyncLock _mutex = new AsyncLock();
        private int i = 0;
        public void Execute()
        {
            Console.WriteLine("before call foo1: "+ i);

            Foo1().ContinueWith(new Action<Task>(t =>
            {
                Console.WriteLine("foo1 completed: " + i);
            }));

            Console.WriteLine("after call foo1: " + i);

            Console.WriteLine("before call foo2: " + i);

            Foo2().ContinueWith(new Action<Task>(t =>
            {
                Console.WriteLine("foo2 completed: " + i);
            }));

            Console.WriteLine("after call foo2: " + i);
        }

        public async Task Foo1()
        {
            using (await _mutex.LockAsync())
            {
                await Task.Delay(TimeSpan.FromSeconds(1));
                Console.WriteLine("Foo1 start: " + i);
                await DoSomethingAsync(1);
                Console.WriteLine("Foo1 end: " + i);
            }
        }

        public async Task Foo2()
        {
            using (await _mutex.LockAsync())
            {
                Console.WriteLine("Foo2 start: " + i);
                //await Task.Delay(TimeSpan.FromSeconds(1));
                await DoSomethingAsync(2);
                Console.WriteLine("Foo2 end: " + i);
            }
        }

        private Task DoSomethingAsync(int j)
        {
            return Task<string>.Run(() =>
            {
                Thread.Sleep(2000);
                i = j;
            });
        }
    }

运行结果如下:



转:http://www.cnblogs.com/1zhk/p/5269279.html

小鱼的淘宝店铺-多多支持哇

可等待的控制台应用 (.NET)

视频在线上传+队列转换FLV+水印+捉图+修复+获时+转3GP(API语言不限,开视频站必备!)

前些天有人贴出了一些代码来让 Async/Await 用起来更简单。他们走的方向是错的,看起来更像是 OnNext/OnError/OnCompleted 的 RXs 模型。错误的原因在于,它并不支持等待。
通常来说,你写的任何 Asyn 代码都会在某个时刻需要同步,所以它必须是可等待的。这就是为什么 async void 是个非常非常狡猾的用法,只应在 event handler 使用,但我们先别提那些了。
我跟写原先那篇文章的小伙子谈话时,指出更典型的用法应该是这样的:

代码 复制 - 运行

class Program
{
    static void Main(string[] args)
    {

        new Program().Backup();
        Console.ReadLine();
    }


    public async void Backup()
    {
        var backupStatus = await BackupAsync();
    }


    public async TaskBackupAsync()
    {
        return await Task.Run(() => "groovy");
    }

}

另一个犀利的读者指出,你永远不应该用 async void (我这样写是为了尽量跟原作者贴的代码保持一致),而我的代码能正常运行的唯一原因是用了 Console.ReadLine(),阻塞了主线程。
我确实知道我永远不该用 async void ,所以我开始尝试贴出一个改进版本。重要的一点是,我用的是 ConsoleApplication 。所以我尝试这样:

代码 复制 - 运行

class Program
{
    private  static async void Main(string[] args)
    {
        await new Program().Backup();
    }


    public async Task Backup()
    {
        var backupStatus = await BackupAsync();
        await Task.Delay(5000); //simulate some work
        Console.WriteLine(backupStatus);
    }


    public async TaskBackupAsync()
    {
        return await Task.Run(() => "groovy");
    }
}

编译器发出了抱怨,不允许 async void 的 main 方法。Error 如下:
‘NonAwaitingConsoleApplication.Program.Main(string[])’: an entry point cannot be marked with the ‘async’ modifier
好吧,那改成这样呢?

代码 复制 - 运行

class Program
{
    private static void Main(string[] args)
    {
        Task.Run(() => MainAsync(args)).Wait();
    }

    static async void MainAsync(string[] args)
    {
        Console.WriteLine(DateTime.Now.ToLongTimeString());
        await new Program().Backup();
        Console.WriteLine(DateTime.Now.ToLongTimeString());
    }

    public async Task Backup()
    {
        var backupStatus = await BackupAsync();
        await Task.Delay(5000); //simulate some work
        Console.WriteLine(backupStatus);
    }


    public async TaskBackupAsync()
    {
        return await Task.Run(() => "groovy");
    }
}

结果它直接闪退了……嗯。有意思。原因在于,在 ConsoleApplication 中没有 SynchronizationContext 。所以线程直接返回到了操作系统,导致程序提前退出。并不是我们想要的结果。怎么办呢?

幸运的是,有一个非常聪明的小伙子 (我高度赞扬) 叫 Stephen Cleary ,他写了一个很棒的 Extension 集,共同参与开发的还有 Stephen Toub (他显然是经验丰富的),所以我充分信任这个库。它叫 NitoAsyncEx 。也可以从 NuGet 获取到它: Nito.AsyncEx
总之,有了这个库,我们就可以写出这样的 AwaitingConsoleApplication 了:

代码 复制 - 运行

internal class Program
{
    private static void Main(string[] args)
    {
        AsyncContext.Run(() => MainAsync(args));
    }

    static async void MainAsync(string[] args)
    {
        Console.WriteLine(DateTime.Now.ToLongTimeString());
        await new Program().Backup();
        Console.WriteLine(DateTime.Now.ToLongTimeString());
    }

    public async Task Backup()
    {
        var backupStatus = await BackupAsync();
        await Task.Delay(5000); //simulate some work
        Console.WriteLine(backupStatus);
    }


    public async TaskBackupAsync()
    {
        return await Task.Run(() => "groovy");
    }
}



注意其中用到的 AsyncContext ,是神奇的 NitoAsyncEx 类让它成为可能。我强烈建议你看看这个类的内部实现 (可以用 Reflector 看到,或者看 Codeplex 上的 source ),看看它的原理。 Stephen 替你做了很多工作,例如确保存在有效的 SynchronizationContext 。请有空看一看。最好看看整个库,它是个很有用的库。
运行这段代码,输出如下,正是我们想要的;然后就退出了(正常退出)
  • 10:52:21


  • groovy


  • 10:52:26




源:http://www.oschina.net/translate/awaitable-console-application
小鱼的淘宝店铺-多多支持哇