0

我有一个 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 个对象的列表执行此操作的最佳方法是什么?

我创建了一个通用对象,它现在执行所有物理搜索(替换 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. 
    } 
}
4

2 回答 2

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>某种意义上不需要是通用的。我希望这有帮助。

附言。我在没有编译器帮助的情况下将其从头顶上写下来,所以请注意拼写错误。

于 2009-06-23T19:37:05.757 回答
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 上的无限循环的可能性......

于 2009-06-24T15:01:52.320 回答