동일한 HttpClient 인스턴스를 사용하는 다른 메서드에서 4 개의 HttpClient 요청을 수행해야합니다. 이는 스레드 안전 문제를 일으키는 것으로 생각됩니다. 내가 더 설명해 줄께.비동기 중 스레드 안전 문제,이 문제를 해결하는 방법
Windows Phone 애플리케이션에서 'MainViewModel'클래스가 개발 중입니다. 이 클래스에는 웹 서버에서 데이터를 가져와 응답을 처리하는 비동기 메소드가 있습니다. 비동기 메서드의 이름은 'LoadData'입니다. 나는이 클래스에서 2 개의 비동기 메서드 ('ScheduleArrayAsync'및 'CurrActivityAsync')를 사용하여 서버에서 가져 오는 데이터를 처리하는 데 도움을줍니다.
'LoadData'메서드에서 3 가지 요청의 응답을 처리하는 동안 3 개의 HttpClient 요청 (이 부분은 매력처럼 작동 함)을 처리하는 동안 'ScheduleArrayAsync'메서드를 호출해야합니다. 거기에서 새로운 HttpClient Request (여기에 문제가있다)를 만들어야한다. 이 마지막 요청은 생성되지 않으며 try/catch 문을 사용할 때도 오류 코드가 생성되지 않습니다.
내가 스레드 문제라고 생각하게 만드는 이유는 마지막 HttpClient 요청을 테스트와 마찬가지로 'LoadData'메서드로 옮기면 다시 작동하기 때문입니다.
MainViewModel 클래스 : - :
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
}
}
내가 문제를 잘 이해하고 있습니까 - 아래
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 클래스입니다? 그것을 극복하는 방법? 정말 'LoadData'
편집 에서 'ScheduleArrayAsync'에서 마지막 HttpClient를 요청을하지해야하므로 그냥 내 각 방법의 문제를 해결하기 위해 내 노력하는 동안 나는 HttpClient를의 다른 인스턴스을 한 것으로 언급하고 싶었다 RequestResponse 클래스 앞에서 언급했듯이, 'LoadData'메소드에서 네 번째 요청을 호출하면 모든 것이 httpclient의 한 인스턴스 일 때도 의도 된대로 작동합니다.
같은 HttpClient 인스턴스를 사용합니다. 그리고 당신은 왜 이것을합니까? 너는 어떻게 든 그것에 붙어 있니? 새로운 것을 만들 수 있고 그런 문제는 없습니다. – nvoigt
@nvoigt - 내가 게시 할 편지에 거의 : –
@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