Читая недавно F #, мне кажется, что "async" и "!" (Bang!: P) довольно полезные функции. (Не по теме, это пример того, что язык программирования является не только темой академических исследований, но и реальной, продуктивной темой проектирования).
Ниже из презентации PDC 2008 Луки Болоньезе:
let internal loadPrices ticker = async {
let url = "http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=9&e=30&f=2008&g=d&a=2&b=13&c=1986&ignore=.csv"
let req = WebRequest.Create(url)
let! resp = req.AsyncGetResponse() //athos: need F# Powerpack
let stream = resp.GetResponseStream()
let reader = new StreamReader(stream)
let! csv = reader.AsyncReadToEnd()
let prices =
csv.Split([|'\n'|])
|> Seq.skip 1
|> Seq.map (fun line -> line.Split([|','|]))
|> Seq.filter (fun values -> values |> Seq.length = 7)
|> Seq.map (fun values ->
System.DateTime.Parse(values.[0]),
float values.[6])
return prices }
Замечательно то, что обратный вызов обрабатывается изящно: программистам не нужно заботиться о BackgroundWorker или Theads 'Join ().
Итак, в C # есть изящное решение для реализации F # "aync" и "!" функции?
Например, возможно ли выполнить «асинхронный ... run ... callback», как показано ниже, или аналогичным способом без усилий?
public void GetApplicationSettings()
{
async(objAsyncRunner = new System.Async.Runner() ) //similar to "using" in C#
run // similar to "if" in C#
{
string url = "http://ichart.finance.yahoo.com/table.csv?s=" + ticker + "&d=9&e=30&f=2008&g=d&a=2&b=13&c=1986&ignore=.csv"
var req = WebRequest.Create(url);
var resp = req.AsyncGetResponse();
}
callback run // similar to "if else" in C#
{
var stream = resp.GetResponseStream();
var reader = new StreamReader(stream);
var csv = reader.AsyncReadToEnd();
}
callback // similar to "else" in C#
{
var prices = csv.Split('\n').....;
}
}
пс. Я знаю, некоторые из вас, ребята, скажут: Афон, просто используйте F #!
да ... я не против F #, но нужно время, чтобы изменить весь отдел, прежде чем я надеюсь позаимствовать некоторые достоинства у F #.
Я знаю, что есть некоторая концепция программирования Aspect для расширения возможностей C #. Однако он все еще не достиг уровня F #.
Например, я могу расширить PostSharp с http://www.sharpcrafters.com, чтобы путем простого присвоения атрибута методу принудительно запускать его в выделенном потоке:
[RunInADedicatedThread(Async = true)]
public void GetApplicationSettings()
{ ... }
при условии, что атрибут подготовлен:
[Serializable]
[AttributeUsage( AttributeTargets.Method | AttributeTargets.Class )]
[MulticastAttributeUsage( MulticastTargets.Method )]
public sealed class RunInADedicatedThreadAttribute : MethodInterceptionAspect
// MethodInterceptionAspect is extending PostSharp
{
public bool Async { get; set; }
public override void OnInvoke( MethodInterceptionArgs args )
{
if (Async)
{
//MyThreadPool is my extention for PostSharp
MyThreadPool.GetThread().ExecuteAsync(
() =>
{
args.Proceed();
} );
return;
}
MyThreadPool.GetThread().Execute( args.Proceed );
}
}
Это немного помогает, но все равно не уровень F #:
- Запросы «Выполнить в выделенном потоке, асинхронно» определяются не для вызова, а для самого метода GetApplicationSettings ()! Этот метод может быть переименован в GetApplicationSettingsAsynchronously (), не так ли;
- также, это не может помочь части обратного вызова;
- не говоря уже о "асинхронной" функции F # для использования меньшего количества потоков ... сейчас я могу даже отказаться от этой "расширенной" функции ...