Just saw this post today:
http://www.outofmemory.co.uk/entity-framework-5-dramatically-faster-in-net-4-5/
Kudos to the EF team for great progress :-)
Just saw this post today:
http://www.outofmemory.co.uk/entity-framework-5-dramatically-faster-in-net-4-5/
Kudos to the EF team for great progress :-)
Now that we have the new nifty async support built into C# you might wonder how you can access your old API’s as if they were async.
Now before I show any code, I have to warn that the code posted here will only wrap your existing sync methods as a Task of T.
You will be able to consume them as if they were async, and in some cases this might be enough, and in other cases, such as IO scenarios, you really should rewrite the methods to use the proper async versions of the IO methods.
The wrapper code provided here may still be a decent start for you to do this, since you can start migrating code to use async calls, while you rewrite the methods that need rewriting later.
class Program
{
static void Main(string[] args)
{
Consumer();
Console.WriteLine("----");
Console.ReadLine();
}
private async static void Consumer()
{
//consume the sync method as if it was async
var b = await Wrap(() => NonAsyncMethod(1, ""));
Console.WriteLine("got result back {0}",b);
}
//this might be one of your old or 3rd party methods
private static int NonAsyncMethod(int a, string b)
{
System.Threading.Thread.Sleep(2000); //emulate some slow code
return 5;
}
private static Task<T> Wrap<T>(Func<T> selector)
{
return Task.Factory.StartNew(selector);
}
}
This is another PoC, building recursive code with continuations using the Async CTP.
The code creates a fake fiber, which can be suspended and resumed, thus allowing us to “step” through its actions.
This technique could be useful when building an interpreting language where you might want to step through the expressions.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Runtime.CompilerServices;
namespace ConsoleApplication7
{
class Program
{
static void Main(string[] args)
{
FakeFiber f = new MyFiber();
f.Run();
while (true)
{
//tell fiber to continue
f.Continue();
Console.ReadLine();
}
}
}
public class MyFiber : FakeFiber
{
//recursive loop that never throws stack overflow
async void DoLoop(int count)
{
await Yield(); //clear callstack
Console.WriteLine("{0} {1}", count, System.Threading.Thread.CurrentThread.ManagedThreadId);
//we can fetch values from other functions too
//w/o blowing the call stack
var i = await IntFunc();
Console.WriteLine("got func result {0}",i);
if (count == 0)
return;
DoLoop(count - 1);
}
private async Task<int> IntFunc()
{
await Yield(); //clear callstack
return 1;
}
public override void Run()
{
DoLoop(100000);
}
}
public abstract class FakeFiber
{
public abstract void Run();
private Task currentTask;
public bool IsCompleted = false;
public void Continue()
{
var task = currentTask;
if (task != null)
{
task.Start();
task.Wait();
}
}
protected Task Yield()
{
currentTask = new Task(() => { this.currentTask = null; });
return currentTask;
}
}
}
More info on TPL DataFlow can be found here : http://www.microsoft.com/downloads/en/details.aspx?FamilyID=d5b3e1f8-c672-48e8-baf8-94f05b431f5c
Here is a (naive) F# style Mailbox / Agent using the C# async CTP :
class Program
{
static void Main(string[] args)
{
var agents = new List<MyAgent>();
//create 100 000 agents
for (int i = 0; i < 100000; i++)
agents.Add(new MyAgent());
//buffer some messages
agents.AsParallel().ForAll(a => a.Send(DateTime.Now.ToString()));
//start agents
agents.AsParallel().ForAll(a => a.Run());
//send some more messages
agents.AsParallel().ForAll(a => a.Send(DateTime.Now.ToString()));
Console.ReadLine();
}
}
public class MyAgent : Mailbox<string>
{
public override async void Run()
{
while (true)
{
var message = await Receive();
Console.WriteLine("Agent {0} got {1}",this.Id, message);
}
}
}
public abstract class Mailbox<T>
{
private static int id;
protected Mailbox()
{
this.Id = id++;
}
public int Id { get;protected set; }
BufferBlock<T> buffer = new BufferBlock<T>();
public abstract void Run();
public void Send(T message)
{
buffer.SendAsync(message);
}
protected async Task<T> Receive()
{
return await buffer.ReceiveAsync();
}
}
This way, we can spawn thousands of agents w/o allocating threads for each of them.
The message loop is executed on the threadpool for each iteration and then suspended untill a new message arrives.