2013-10-24 39 views
0

在我的NET 4.5應用程序中,我有一個服務層。在異步模式下處理類執行

我使用調度來發送查詢和接收應答:

實施例:GetPostByIdQuery由GetPostByIdHandler處理並返回GetPostByIdReply。

我該如何更改我的代碼,以便以異步方式處理查詢?

public class Dispatcher : IDispatcher { 

    public TReply Send<TReply>(Query query) where TReply : Reply, new() { 

    Type type = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TReply)); 

    IQueryHandler handler = (IQueryHandler)ObjectFactory.GetInstance(type); 

    try { 

     return (TReply)handler.Handle(query); 

    } catch (Exception exception) { 

     ILogger logger = ObjectFactory.GetInstance<ILogger>(); 
     logger.Send(exception); 
     if (Debugger.IsAttached) throw; 
     return new TReply { Exception = exception }; 

    } 
    } // Send 
} 

更新:考慮到我添加了建議:

public interface IDispatcher { 

    TReply Send<TReply>(Query query) where TReply : Reply, new(); 
    Task<TReply> SendAsync<TReply>(Query query) where TReply : Reply, new(); 

} // IDispatcher 

public class Dispatcher : IDispatcher { 

    public TReply Send<TReply>(Query query) where TReply : Reply, new() { 
    } // Send 

    public Task<TReply> Send<TReply>(Query query) where TReply : Reply, new() { 
    } // Send 

} 

兩個問題:

  1. 我需要重複之內的兩次發送方式,我的代碼?或者可以打另一個?

  2. 而不是有兩個發送方法可以有一個方法與布爾「sendAsync」? 我不知道是否因爲返回類型這有意義將是相同的...

+2

改變你的界面返回'任務' – SLaks

+0

你有什麼具體問題?爲什麼你的案例與其他任何異步方法不同? – usr

+0

所以我只需要添加任務到我的界面和我的類方法?我問這是因爲我的想法是這樣的:TReply發送(查詢查詢,布爾async = false)...所以這樣我就決定何時使用asyn或不。不能這樣做嗎? –

回答

2

如果你想「擁抱異步」,並從中獲得任何真正的好處,你將需要修改IQueryHandler並使之異步,因爲這是真正的工作正在完成。

你從來沒有向我們展示了什麼IQueryHandler做,但你可能會需要編寫新的方法來真正支持異步代碼

public class Dispatcher : IDispatcher { 

    public TReply Send<TReply>(Query query) where TReply : Reply, new() { 
     //(Snip) No changes to the original code 
    } // Send 

    public async Task<TReply> SendAsync<TReply>(Query query) where TReply : Reply, new() { 

    Type type = typeof(IQueryHandler<,>).MakeGenericType(query.GetType(), typeof(TReply)); 

    IQueryHandler handler = (IQueryHandler)ObjectFactory.GetInstance(type); 

    try { 

     return await (TReply)handler.HandleAsync(query); //Uses the new method "Task<TResult> IQueryHandler<TQueryType, TResult>.HandleAsync(TQueryType query)" 

    } catch (Exception exception) { 

     ILogger logger = ObjectFactory.GetInstance<ILogger>(); 
     logger.Send(exception); 
     if (Debugger.IsAttached) throw; 
     return new TReply { Exception = exception }; 

    } 
    } // Send 
} 

如果你不關心寫實時異步代碼的性能改進(它可能不值得更新所有IQueryHandler S的成本),但您仍想使用異步的合意/等待一個緩慢的過程中,你可以通過做

public class Dispatcher : IDispatcher { 

    public TReply Send<TReply>(Query query) where TReply : Reply, new() { 
     //(Snip) No changes to the original code 
    } // Send 

    public Task<TReply> SendAsync<TReply>(Query query) where TReply : Reply, new() { 
     return Task.Run(() => Send<TReply>(query)); 
    } // SendAsync 
} 

但是做一個簡單的包裝,就像我說的,不要預計不會有太多的表現g從這一點,只是方便,所以你的呼叫者不必自己做(也許將來有一段時間,你可以用真正的異步代碼替換它,而不必更新任何使用此函數的調用者)。

0

你可以添加一個新的SendAsync方法,例如:

public Task<TReply> SendAsync<TReply>(Query query) where TReply : Reply, new() 
{ 
    return Task.Run(() => 
    { 
     return Send<TReply>(query); 
    }); 
} 

要回答你的第二個問題,如果你想只露出一個方法簽名一樣Send(Query query, bool sendAsync),讓你的原始Send方法私有的,你可以寫這樣的事情:

public dynamic Send<TReply>(Query query, bool sendAsync) where TReply : Reply, new() 
{ 
    if (sendAsync) 
    { 
     return Task.Run(() => 
     { 
      return Send<TReply>(query); 
     } 
    } 
    else 
    { 
     return Send<TReply>(query); 
    } 
} 

同樣,調用者可以返回並拆箱Object。但是用這種方式來寫就很難看,我只是指出這是可能的。

+1

這只是在它發生在後臺的意義上是異步的 - 人們喜歡異步的性能不在這裏。在API級別將Task.Run()中的同步方法包裝在API級別中是一個不好的主意,因爲它隱藏了用戶的低效率,因爲用戶可能會更好地解決同步呼叫問題。 –

+1

而不是'動態'我會剛剛完成[Task.FromResult](http://msdn.microsoft.com/en-us/library/hh194922.aspx),並讓它返回「任務」同步和異步版本。 –