2010-11-10 67 views
0

我正在开发与vsNET 2010和C#窗体窗体的Windows应用程序。这个应用程序有一个查询服务的用户控件(WCF托管在win服务上),并且需要在不阻止UI的情况下执行此操作。用户控件包含一个将显示结果的网格。我认为我的情况最为常见。我对你的问题是用C#可以做些什么,以使下面的代码运行更平滑,并具有更好的错误处理。我正在使用MehtodInvoker,因此我可以避免为此调用写入两个分离方法 - 等待 - 填充方案。异步调用最佳实践

public void LoadData() 
{ 
    StartWaitProgress(0); 
    ThreadPool.QueueUserWorkItem(x => 
    { 
     try 
     { 
      MyDocMail[] mails; 
      var history = Program.NoxProxy.GetDocumentHistory(out mails, Program.MySessionId, docId); 
      this.Invoke(new MethodInvoker(delegate() 
      { 
       this.SuspendLayout(); 
       gridVersions.Rows.Clear(); 
       foreach (var item in history) 
       { 
        gridVersions.Rows.Add(); 
        int RowIndex = gridVersions.RowCount - 1; 
        DataGridViewRow demoRow = gridVersions.Rows[RowIndex]; 
        demoRow.Tag = item.Id; 
        if (gridVersions.RowCount == 1) 
        { 
         demoRow.Cells[0].Value = Properties.Resources.Document_16; 
        } 
        demoRow.Cells[1].Value = item.Title; 
        demoRow.Cells[2].Value = item.Size.GetFileSize(); 
        demoRow.Cells[3].Value = item.LastModified; 
        demoRow.Cells[4].Value = item.CheckoutBy; 
        demoRow.Cells[5].Value = item.Cotegory; 
       } 
       gridEmails.Rows.Clear(); 
       foreach (var item in mails) 
       { 
        gridEmails.Rows.Add(); 
        int RowIndex = gridEmails.RowCount - 1; 
        DataGridViewRow demoRow = gridEmails.Rows[RowIndex]; 
        demoRow.Tag = item.Id; 
        demoRow.Cells[1].Value = item.From; 
        demoRow.Cells[2].Value = item.To; 
        demoRow.Cells[3].Value = item.Date; 
       } 
       this.ResumeLayout(); 
      })); 
     } 
     catch (Exception ex) 
     { 
      Program.PopError(ex); 
      this.Invoke(new MethodInvoker(delegate() { this.Close(); })); 
     } 
     finally { this.Invoke(new MethodInvoker(delegate() { StopWaitProgress(); })); } 
    }); 
} 

回答

3

有什么不对您的解决方案的,但可以用BackgroundWorker更轻松地完成它。

BackgroundWorker处理线程异常,在WPF窗口调用Invoke,并帮助进度报告和取消。更多例子here

P.S.未来的C#版本可能会更容易 - 请查看Async CTP

+0

你也可以使用.NET 4框架中的任务来清理它。 – 2010-11-10 04:37:35

+0

我已经在C#2.0中尝试过BackgroundWorker解决方案,但我没有看到任何优势,我使用BackgroundWorker将代码分离到多个方法/事件中。在我的应用程序中,有些情况下,我可以在10次调用wcf服务的同一窗体中进行操作。为了加速这个调用,我必须让它们在同一时间(在ThreadPool上并行运行),以便产生BackgroundWorker的10个实例...上面的代码更加紧凑,因为我可以为每个异步调用。 – 2010-11-10 09:12:55

+1

请记住,您可以以编程方式实例化BackgroundWorker,并使用匿名方法或lambda表达式来处理事件(这通常是我所做的)。最好的解决方案取决于你的最终目标。你能详细说明你的意思是“更平滑,更好的错误处理”吗? – 2010-11-10 10:53:07