Мне нужно выполнить 4 запроса HttpClient из разных методов, используя один и тот же экземпляр HttpClient, что, как мне кажется, вызывает проблему безопасности потоков. Позвольте мне объяснить это подробнее.
Внутри приложения для Windows Phone, которое я разрабатываю, есть класс MainViewModel. Этот класс имеет асинхронный метод для получения данных с веб-сервера и обработки ответа. Метод 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
}
}
Я правильно понимаю задачу? Как это преодолеть? так как мне действительно нужно сделать последний запрос HttpClient из «ScheduleArrayAsync», а не из «LoadData»
Изменить Просто хотел упомянуть, что во время моих усилий по решению проблемы у меня был другой экземпляр HttpClient в каждом методе внутри класса RequestResponse. Помимо того, как я упоминал выше, когда я вызываю четвертый запрос из метода «LoadData», все работает так, как задумано, даже если это один экземпляр httpclient.
using the same HttpClient instance
. А ты это зачем? Вы как-то к нему привязаны? Вы можете создать новый и не иметь ни одной из этих проблем. - person nvoigt   schedule 30.03.2014