0

我需要使用相同的HttpClient的实例,我认为造成线程安全问题做不同方法4个HttpClient的请求。让我更多地解释这一点。安全问题,如何解决这个

里面一个Windows Phone应用程序我正在开发有一个“MainViewModel”类。这个类有一个异步方法来从web服务器获取数据并处理响应。 Async方法被命名为'LoadData'。我甚至在这个班,2种异步方法(“ScheduleArrayAsync”和“CurrActivityAsync”),以帮助处理我从服务器获取数据。

从'LoadData'方法我做3 HttpClient请求(这部分工作像魅力),同时处理所有这三个请求的响应,我需要调用'ScheduleArrayAsync'方法。从那里我必须做一个新的HttpClient请求(问题来了)。这最后一个请求将永远不会生成,并且即使在使用try/catch语句时也不会生成错误代码。

是什么让我觉得这是一个线程问题是,如果我将最后HttpClient的请求“LoadData”的方法,只是作为一个测试,它再次工作。

的MainViewModel类: -

public class MainViewModel : INotifyPropertyChanged 
{ 
    public MainViewModel() 
    { 
     this.Employees = new ObservableCollection<Employee>(); 
    } 

    public ObservableCollection<Employee> Employees { get; private set; } 

    private JsonTextWriter jsonW; 

    private string Owner; 

    private RequestResponse reqPList; 

    public bool IsDataLoaded 
    { 
     get; 
     private set; 
    } 
    public async void LoadData() 
    { 
     var baseUri = new Uri("https://uri/"); 

     await CookieHandler.GetCookies(baseUri); // A separate request to get some cookies 

     reqPList = new RequestResponse(); // The class that handle the Httpclinet 

     await reqPList.GetResponse(baseUri, pList); // First request 
     XmlConvertor.ConvertToXml(reqPList.Response); 
     var phoneListResponse = XmlConvertor.XmlString; 

     await reqPList.GetResponse(baseUri, currActiv); // Second request 
     XmlConvertor.ConvertToXml(reqPList.Response); 
     var currActivResponse = XmlConvertor.XmlString; 

     await reqPList.GetResponse(baseUri, sched); // Third request 
     XmlConvertor.ConvertToXml(reqPList.Response); 
     var schedResponse = XmlConvertor.XmlString; 

     //await reqPList.GetSlotInforPOST("154215"); 
     var handler = new DataHandler(); 
     await handler.phoneListHandler(phoneListResponse); 
     await handler.CurrActivitiesHandler(currActivResponse); 
     await handler.ScheduleHandler(schedResponse); 
     /// Do some processing included call this line 

        #region Current activity 
        CurrActivityAsync(item, handler.currActivitiesJSON); 
        #endregion 


     this.IsDataLoaded = true; 
    } 

    private async void CurrActivityAsync(JToken token, string jString) 
    { 
     // Some processing 
    } 

    private async void ScheduleArrayAsync(JToken token, string jString) 
    { 
     try 
     { 
      // Do some more processing and call the fourth request 
          if (addedInfo[0].Contains("slotInfo")) 
           await reqPList.GetSlotInforPOST(addedInfo[1]); 
          else if (addedInfo[0].Contains("vacationInfo")) 
           await reqPList.GetVacationSlotInfoPOST(addedInfo[1], addedInfo[2]); 

     } 
     catch (Exception exp) 
     { 

      var d = exp.Message; 
     } 
    } 

    public event PropertyChangedEventHandler PropertyChanged; 
    private void NotifyPropertyChanged(String propertyName) 
    { 
     PropertyChangedEventHandler handler = PropertyChanged; 
     if (null != handler) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
} 

下面是requestResponse则类: -

public class RequestResponse 
{ 
    public string Response { get; private set; } 

    private HttpClient client = new HttpClient(new HttpClientHandler() 
    { 
     UseCookies = true, 
     CookieContainer = CookieHandler.Cookiejar, 
     AllowAutoRedirect = false, 
     AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip 
    }); 

    public async Task<string> GetResponse(Uri baseuri, string uriString) 
    { 
     if (client.BaseAddress == null) 
     { 
      client.BaseAddress = baseuri; 
     } 
     client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/xhtml+xml")); 
     var response = await client.GetAsync(baseuri + uriString); 
     string webresponse = null; 
     if (response.IsSuccessStatusCode) 
     { 
      var resp = await response.Content.ReadAsByteArrayAsync(); 
      var encode = Encoding.GetEncoding("iso-8859-1"); 
      var respString = encode.GetString(resp, 0, resp.Length - 1); 
      webresponse = respString; 
     } 
     return Response = webresponse; 
    } 

    public async Task<string> GetSlotInforPOST(string timeId) 
    { 
     /// If the method is called from inside 'LoadData' it works. 
     /// But if it is called from inside ScheduleArrayAsync, it will break at line marked with //*** 
     try 
     { 
      var baseUri = new Uri("https://uri/"); 
      const string slotInfo = "cgi-bin/slotInfo.pl"; 

      if (client.BaseAddress == null) 
       client.BaseAddress = baseUri; 
      client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded")); 
      HttpContent content = new FormUrlEncodedContent(new[] 
      { 
       new KeyValuePair<string,string>("timeId",timeId) 
      }); 
      var response = await client.GetAsync(baseUri + slotInfo); // *** 
      string webresponse; 
      if (response.IsSuccessStatusCode) 
      { 
       var respo = await client.PostAsync(baseUri + slotInfo, content); 
       var resp = await respo.Content.ReadAsByteArrayAsync(); 
       var encode = Encoding.GetEncoding("iso-8859-1"); 
       var respString = encode.GetString(resp, 0, resp.Length - 1); 
       webresponse = respString; 

      } 
     } 
     catch (Exception exp) 
     { 
      var s = exp.Message; 
     } 
     return Response; 
    } 

    public async Task<string> GetVacationSlotInfoPOST(string vacationId, string date) 
    { 
     // Do some HttpClient Request 
    } 
} 

我是否了解的问题吗?如何克服它?我真的需要从“ScheduleArrayAsync”从“LoadData”

编辑 使最后HttpClient的请求,而不是只是想提一提,在我的努力来解决这个问题,我的HttpClient的不同实例中的每个方法中RequestResponse类。除了我上面提到的,当我打电话从内部“LoadData”一切法第四请求工作,因为它的目的是,即使它的HttpClient的一个实例。

+1

'使用相同的HttpClient实例'。你为什么这么做?你有没有附加到它?你可以创建一个新的,并没有任何这些问题。 – nvoigt

+1

@nvoigt - 差不多就是我要发布的信:) –

+0

@nvoigt是不是更好的性能明智?我想我在这里读了一些关于这方面的内容: - http://social.msdn.microsoft.com/Forums/en-US/4e12d8e2-e0bf-4654-ac85-3d49b07b50af/best-practice-usage-of-httpclient-for- rest-calls-maximum-throughput?forum = netfxnetcom – DreamNet

回答

2

这可能是您在某些方法中用作签名的异步无效。使用async void将阻止调用函数捕获抛出异常。异步void方法抛出的异常只能被全局异常处理程序捕获。

+0

虽然我同意使用'async void'是问题的根源,但这并不是因为它吞下异常。恰恰相反; 'async void'会非常大声地表示异常。 –

+0

@StephenCleary我的修改听起来更好吗? –

+0

是的,我认为这样更正确。 –

0

最后我有固定的,这要归功于达雷尔。

要解决我需要改变“CurrActivityAsync”方法的签名的问题。

private async void CurrActivityAsync(JToken token, string jString) 

private void CurrActivityAsync(JToken token, string jString) 

由于这种方法有它里面没有任何的await这就是为什么它并不需要异步的签名。我的坏我没有在我原来的帖子中提到过。

这是我唯一需要做的事情,但我甚至将我的'ScheduleArrayAsync' 的签名更改为对于Async更加正确。

private async void ScheduleArrayAsync(JToken token, string jString) 

private async Task ScheduleArrayAsync(JToken token, string jString) 

达雷尔请您写了一个答案最后的评论,所以你得到一些积分。