对委托/ IAsyncResult调用进行通用化

时间:2009-06-23 15:42:52

标签: c# delegates iasyncresult

我有一个WCF Web服务,当前正在搜索多个硬编码的dtSearch索引,然后合并生成的数据集以返回给客户端。我有以下C#代码:

public class Search : ISearch
{
    delegate DataTable PDelegate(string term, int cid);
    delegate DataTable CDelegate(string term, int sid);

    public DataTable SearchPIndex(string term, int cid) {/* do search */}
    public DataTable SearchCIndex(string term, int sid) {/* do search */}

    public DataTable SearchAll(string term, int cid, int sid)
    {
        PDelegate pDel = new PDelegate(SearchPIndex);
        CDelegate cDel = new CDelegate(SearchCIndex);

        IAsyncResult pInvoke = pDel.BeginInvoke(term, cid, null, null);
        IAsyncResult cInvoke = cDel.BeginInvoke(temr, sid, null, null);

        DataTable pResults = pdel.EndInvoke(pInvoke);
        DataTable cResults = cdel.EndInvoke(cInvoke);

        // combine the DataTables and return them
    }
}

我的问题是:将此逻辑移动到一个单独的泛型类中的最佳方法是什么,并为1 ... n个对象的List执行此操作?

我有一个我创建的通用对象现在执行所有物理搜索(替换SearchPIndex和SearchCIndex方法),但我不确定如何将委托/ IAsyncResult调用集成到泛型中。

我可以遵循最佳做法吗?


编辑:对不起...第一次作为网站上的“用户”...“回答”似乎比上面的“评论”更好。

我打算玩它,但这会在方法中起作用吗?

SearchAsync sa = new SearchAsync(SearchIndex); 
var asyncs = new List<IAsyncResult>(); 

foreach(int index in indices) 
{ 
    asyncs.Add(sa.BeginInvoke(term, index, null, null));
} 

var tables = new List<DataTable>(); 
foreach(IAsyncResult iar in asyncs)
{ 
    try
    { 
        tables.Add(sa.EndInvoke(iar)); 
    } 
    catch 
    { 
        //etc. 
    } 
}

2 个答案:

答案 0 :(得分:0)

首先要注意的是你的代码只需要1个委托类型:

delegate DataTabe SearchAsync(string term, int index);

这意味着SearchAll方法可以是:

public DataTable SearchAll(string term, List<int> indices) 
{
    var asyncs = new List<IAsyncResult>();
    foreach(int index in indices) 
    {
         SearchAsync sa = new SearchAsync(NewMethodSearchWithTermAndIndexParemeter);
         asyncs.Add(sa.BeginInvoke(term, index, null, null));
    }
    var tables = new List<DataTable>();
    foreach(IAsyncResult iar in asyncs) 
    {
         try 
         {
              tables.Add(sa.EndInvoke(iar));
         }
         catch 
         {
             ...appropriately handle
         } 
    }
    .... merge tables
}

我不认为你的新方法在<T>意义上需要是通用的。我希望这有帮助。

PS。在没有编译器的帮助下,我把它从头顶下来,所以请注意拼写错误。

答案 1 :(得分:0)

好的,在进一步使用谷歌和你非常有用的链接后,这就是我现在所拥有的:

public class Search : ISearch
{
    delegate DataTable SearchAsync(int stypeid, string term, int? cid, int? sid);
    List<DataTable> tables;

    private void ProcessCallBack(IAsyncResult result)
    {
        AsyncResult asyncResult = (AsyncResult)result;
        SearchAsync async = (SearchAsync)asyncResult.AsyncDelegate;

        if(tables == null)
        {
            tables = new List<DataTable>();
        }

        try
        {
            tables.Add(async.EndInvoke(result));
        }
        catch(Exception ex)
        {
            /* handle error */
            tables.Add(null);
        }
    }

    public DataTable SearchIndex(int stypeid, string term, int? cid, int? sid) 
    {/* do search */}

    public DataTable SerachGlobal(string term, int? cid, int? sid)
    {
        List<SearchTypes> types ...; /* load types from db */
        SearchAsync async = new SearchAsync(SearchIndex);
        AsyncCallback callBack = new AsyncCallback(ProcessCallBack);

        foreach(SearchType t in types)
        {
            async.BeginInvoke(t.searchtypeid, term, cid, sid, callBack, null);
        }

        do
        {
            Thread.Sleep(100);
        }
        while(tables == null || tables.Count < types.Count);

        /* combine the tables */

    }
}

这看起来怎么样? 唯一让我担心的是do / while ...

的无限循环的可能性