2

在我的 C# 应用程序中,我有一个服务引用,我在其中一遍又一遍地执行相同的调用。

void GetData()
{
  var request = new GetDataRequest { someData = "blabla" } ;
  service.GetDataCompleted += (sender, args) => 
  {
      // do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times
  }
  service.GetDataAsync(request);
}

void GetData2()
{
  var request = new GetDataRequest { someData = "blabla2" } ;
  service.GetDataCompleted += (sender, args) => 
  {
      // do something different here!
  }
  service.GetDataAsync(request);
}

我怀疑这会以某种方式泄漏,因为我每次都注册一个新的事件处理程序。是真的吗,如果是的话,我该如何避免呢?

4

1 回答 1

0

你可以这样做:

void GetData()
{
  var request = new GetDataRequest { someData = "blabla" } ;

  EventHandler handler = null; 
  handler = (sender, args) => 
  {
      // do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times

      //remove itself
      service.GetDataCompleted -= handler;
  };

  service.GetDataCompleted += handler;
  service.GetDataAsync(request);
}

void GetData2()
{
  var request = new GetDataRequest { someData = "blabla2" } ;
  EventHandler handler = null; 

  handler = (sender, args) => 
  {
      // do something different here!

      //remove itself
      service.GetDataCompleted -= handler;
  };

  service.GetDataCompleted += handler;
  service.GetDataAsync(request);
}

编辑:关于仅将调用同步到其处理程序:如果您GetData2()立即调用,GetData()您将从上面的代码中得到不可预测的结果。大多数情况下,两个处理程序都会为这两个请求调用。

最简单的解决方案是每个方法都有单独的service代理对象。GetDataX()这样您就可以同时发出两个请求。

但是,如果您被迫仅使用单个代理对象并发出并发请求 - 可能会调用错误的处理程序。一种选择是您可以使用一个UserState对象来识别您的请求,因此即使调用了错误的处理程序,它也可以检测到它是为错误的请求而调用的。

void GetData()
{
  var request = new GetDataRequest { someData = "blabla" } ;

  Guid userState = Guid.NewGuid();

  EventHandler<GetDataCompletedEventArgs> handler = null; 
  handler = (sender, args) => 
  {
      if (userState.Equals(args.UserState)) 
      {
          // do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times

          //remove itself
          service.GetDataCompleted -= handler;
      }
  };

  service.GetDataCompleted += handler;
  service.GetDataAsync(request, userState);
}

void GetData2()
{
  var request = new GetDataRequest { someData = "blabla2" } ;

  Guid userState = Guid.NewGuid();

  EventHandler<GetDataCompletedEventArgs> handler = null; 
  handler = (sender, args) => 
  {
      if (userState.Equals(args.UserState)) 
      {
          // do something different here!

          //remove itself
          service.GetDataCompleted -= handler;
      }
  };

  service.GetDataCompleted += handler;
  service.GetDataAsync(request, userState);
}

现在,如果您发出并发请求,并且即使为这两个请求调用了两个处理程序,也只有正确请求的正确代码将在if条件内运行。

如果您不想使用UserState,有一些方法可以同步调用,这样处理程序就不会相互交叉。Tasks以下是一种确保请求一个接一个发生的非阻塞方式。

Task<GetDataResponse> GetData()
{
  var src = new TaskCompletionSource<GetDataResponse>();     

  var request = new GetDataRequest { someData = "blabla" } ;
  EventHandler handler = null; 
  handler = (sender, args) => 
  {
      // do something; i'm afraid that this is executed multiple times, as GetData() is called multiple times

      src.SetResult(args.Result);

      //remove itself
      service.GetDataCompleted -= handler;
  };

  service.GetDataCompleted += handler;
  service.GetDataAsync(request);

  return src.Task;
}

Task<GetDataResponse> GetData2()
{
  var src = new TaskCompletionSource<GetDataResponse>();

  var request = new GetDataRequest { someData = "blabla2" } ;
  EventHandler handler = null; 

  handler = (sender, args) => 
  {
      // do something different here!

      src.SetResult(args.Result);

      //remove itself
      service.GetDataCompleted -= handler;
  };

  service.GetDataCompleted += handler;
  service.GetDataAsync(request);

  return src.Task;

}

在调用方法中,确保它们被一个接一个地调用:

GetData().ContinueWith( t => GetData2() );
于 2013-07-30T15:30:18.673 回答