在执行 get 方法的异步调用时在主代码中等待
waiting in the main code while asynchronous call for get method executes
void main() {
OpenWeatherApiClient.getCurrentLocationWeatherAsync(55.513434, -37.53434, (x) => {
Console.WriteLine(x.coord.lat);
Console.ReadLine();
});
}
Console.WriteLine("this should happen before");
/// I want to hold the the function here till the call back returns and executes the above logic
/// the asynchronous function
public static void getCurrentLocationWeatherAsync(double latitude, double longitude, Action<WeatherData> callback) {
//weather from one station
string weatherSearch = "weather?lat={0}&lon={1}";
var url = string.Concat(baseUrl, weatherSearch);
//Customize the URL according to the geo location
url = string.Format(url, latitude, longitude);
//Syncronous consumption
var asynClient = new WebClient();
//add Appid for verification
asynClient.Headers.Add(APPIDName, APPID);
asynClient.OpenReadCompleted += (o, a) => {
if (callback != null) {
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeatherData));
callback(ser.ReadObject(a.Result) as WeatherData);
}
};
asynClient.OpenReadAsync(new Uri(url));
}
在将请求解析为数据契约后,我已经处理了这个异步获取方法。虽然我想保留主要方法,直到完全执行委托中的 getcall 和关联代码。
将来我想要的是同时调用不仅仅是 get 方法并持有它们直到它们全部执行。
之后我将继续进行主要操作,因为每个 get 调用的数据都是相关的
如果我理解正确的话:
private static readonly List<Task> weatherTasks = new List<Task>();
public static void GetCurrentLocationWeatherAsync(double latitude, double longitude, Action<WeatherData> callback)
{
// ...
weatherTasks.Add(asynClient.OpenReadTaskAsync(new Uri(url)));
}
public static void WaitForAllWeatherCalls()
{
Task.WaitAll(weatherTasks.ToArray());
weatherTasks.Clear();
}
创建任务列表,然后将 OpenReadAsync
更改为 OpenReadTaskAsync
并将任务放入列表中。方法 WaitForAllWeatherCalls
然后只是等待所有当前 运行 任务,然后清除任务(请注意代码不是线程安全的)。
为什么这段代码不是线程安全的:
假设我们有一个线程 A 和一个线程 B。A 多次调用 GetCurrentLocationWeatherAsync
然后想要等待这些调用。所以线程 A 调用 WaitForAllWeatherCalls
并且现在正在等待。当线程 A 正在等待时,线程 B 也想获取一些天气数据。线程 B 多次调用 GetCurrentLocationWeatherAsync
。 Task列表现在包含线程A的一些任务和线程B的一些任务,当线程A的等待结束后问题就来了,因为任务列表会被清空。当线程 B 想要等待他的所有数据时,列表中将没有任何任务,线程 B 甚至不会暂停一次。
更好的版本:
class WeatherGatherer
{
private readonly List<Task> weatherTasks = new List<Task>();
public void GetCurrentLocationWeatherAsync(double latitude, double longitude, Action<WeatherData> callback)
{
// ...
weatherTasks.Add(asynClient.OpenReadTaskAsync(new Uri(url)));
}
public void WaitForAllWeatherCalls()
{
Task.WaitAll(weatherTasks.ToArray());
weatherTasks.Clear();
}
}
洞的东西现在在 class 而不是静态的。 class 本身仍然不是线程安全的,但是如果你总是为一组 'weather-data gathering' 创建一个实例,你就不会有问题。
请记住,线程安全只有在您拥有多个线程时才会成为问题。
执行相同上述逻辑的任何替代方案也非常好
我以前是这样做的,但无法继续,因为事件不会return反序列化对象
//public static async Task<WeatherData> getCurrentLocationWeatherAsync(double latitude, double longitude)
//{
// //weather from one station
// string weatherSearch = "weather?lat={0}&lon={1}";
// var url = string.Concat(baseUrl, weatherSearch);
// //Customize the URL according to the geo location
// url = string.Format(url,latitude, longitude);
// //Syncronous consumption
// var asynClient = new WebClient();
// //add Appid for verification
// asynClient.Headers.Add(APPIDName,APPID);
// asynClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(asyncClient_DownloadStringCompleted);
// // API call
// var response = await asynClient.DownloadStringTaskAsync(url);
// //content=content.Replace("3h", "precipitation__3h");
// //create Json Serializer and parse the response
//}
//static void asyncClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
//{
// // Create the Json serializer and parse the response
// DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(WeatherData));
// using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(e.Result)))
// {
// // deserialize the JSON object using the WeatherData type.
// var weatherData = (WeatherData)serializer.ReadObject(ms);
// // return weatherData;
// }
//}
void main() {
OpenWeatherApiClient.getCurrentLocationWeatherAsync(55.513434, -37.53434, (x) => {
Console.WriteLine(x.coord.lat);
Console.ReadLine();
});
}
Console.WriteLine("this should happen before");
/// I want to hold the the function here till the call back returns and executes the above logic
/// the asynchronous function
public static void getCurrentLocationWeatherAsync(double latitude, double longitude, Action<WeatherData> callback) {
//weather from one station
string weatherSearch = "weather?lat={0}&lon={1}";
var url = string.Concat(baseUrl, weatherSearch);
//Customize the URL according to the geo location
url = string.Format(url, latitude, longitude);
//Syncronous consumption
var asynClient = new WebClient();
//add Appid for verification
asynClient.Headers.Add(APPIDName, APPID);
asynClient.OpenReadCompleted += (o, a) => {
if (callback != null) {
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(WeatherData));
callback(ser.ReadObject(a.Result) as WeatherData);
}
};
asynClient.OpenReadAsync(new Uri(url));
}
在将请求解析为数据契约后,我已经处理了这个异步获取方法。虽然我想保留主要方法,直到完全执行委托中的 getcall 和关联代码。 将来我想要的是同时调用不仅仅是 get 方法并持有它们直到它们全部执行。 之后我将继续进行主要操作,因为每个 get 调用的数据都是相关的
如果我理解正确的话:
private static readonly List<Task> weatherTasks = new List<Task>();
public static void GetCurrentLocationWeatherAsync(double latitude, double longitude, Action<WeatherData> callback)
{
// ...
weatherTasks.Add(asynClient.OpenReadTaskAsync(new Uri(url)));
}
public static void WaitForAllWeatherCalls()
{
Task.WaitAll(weatherTasks.ToArray());
weatherTasks.Clear();
}
创建任务列表,然后将 OpenReadAsync
更改为 OpenReadTaskAsync
并将任务放入列表中。方法 WaitForAllWeatherCalls
然后只是等待所有当前 运行 任务,然后清除任务(请注意代码不是线程安全的)。
为什么这段代码不是线程安全的:
假设我们有一个线程 A 和一个线程 B。A 多次调用 GetCurrentLocationWeatherAsync
然后想要等待这些调用。所以线程 A 调用 WaitForAllWeatherCalls
并且现在正在等待。当线程 A 正在等待时,线程 B 也想获取一些天气数据。线程 B 多次调用 GetCurrentLocationWeatherAsync
。 Task列表现在包含线程A的一些任务和线程B的一些任务,当线程A的等待结束后问题就来了,因为任务列表会被清空。当线程 B 想要等待他的所有数据时,列表中将没有任何任务,线程 B 甚至不会暂停一次。
更好的版本:
class WeatherGatherer
{
private readonly List<Task> weatherTasks = new List<Task>();
public void GetCurrentLocationWeatherAsync(double latitude, double longitude, Action<WeatherData> callback)
{
// ...
weatherTasks.Add(asynClient.OpenReadTaskAsync(new Uri(url)));
}
public void WaitForAllWeatherCalls()
{
Task.WaitAll(weatherTasks.ToArray());
weatherTasks.Clear();
}
}
洞的东西现在在 class 而不是静态的。 class 本身仍然不是线程安全的,但是如果你总是为一组 'weather-data gathering' 创建一个实例,你就不会有问题。
请记住,线程安全只有在您拥有多个线程时才会成为问题。
执行相同上述逻辑的任何替代方案也非常好
我以前是这样做的,但无法继续,因为事件不会return反序列化对象
//public static async Task<WeatherData> getCurrentLocationWeatherAsync(double latitude, double longitude)
//{
// //weather from one station
// string weatherSearch = "weather?lat={0}&lon={1}";
// var url = string.Concat(baseUrl, weatherSearch);
// //Customize the URL according to the geo location
// url = string.Format(url,latitude, longitude);
// //Syncronous consumption
// var asynClient = new WebClient();
// //add Appid for verification
// asynClient.Headers.Add(APPIDName,APPID);
// asynClient.DownloadStringCompleted += new DownloadStringCompletedEventHandler(asyncClient_DownloadStringCompleted);
// // API call
// var response = await asynClient.DownloadStringTaskAsync(url);
// //content=content.Replace("3h", "precipitation__3h");
// //create Json Serializer and parse the response
//}
//static void asyncClient_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
//{
// // Create the Json serializer and parse the response
// DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(WeatherData));
// using (var ms = new MemoryStream(Encoding.Unicode.GetBytes(e.Result)))
// {
// // deserialize the JSON object using the WeatherData type.
// var weatherData = (WeatherData)serializer.ReadObject(ms);
// // return weatherData;
// }
//}