2015-05-24 60 views
0
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)); 
} 

我有女仆这个异步get方法,将请求解析成数据合同后。虽然我想持有主方法,直到委托中的getcall和相关代码完全执行。 未来我想要的是同时调用多个get方法,并保持它们直到所有方法都执行。 这之后,我将在主进行,因为每个GET调用数据取决于在主代码中等待,异步调用get方法执行

+1

,你为什么要跑异步代码,当你真的想要执行线程? – poke

+0

对不起,我没有明白。但我正在使用异步服务调用,因为我必须调用多个服务方法,并且不想等待第一个调用的响应,然后再继续执行第二个调用 – Ahsan

+0

您想要多次调用getCurrentLocationWeatherAsync方法,然后等待直到所有人都完成了,或者我理解你的问题是错的? –

回答

1

如果我理解正确你:

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(); 
} 

创建任务列表然后更改OpenReadAsyncOpenReadTaskAsync,并把任务进入列表。方法WaitForAllWeatherCalls然后只是等待所有当前正在运行的任务,然后清除任务(请注意代码不是线程安全的)。

为什么这段代码不是线程安全的: 假设我们有一个线程A和一个线程B.多次调用GetCurrentLocationWeatherAsync然后想要等待这些调用。因此,线程A呼叫WaitForAllWeatherCalls,现在正在等待。虽然线程A正在等待线程B也想获取一些天气数据。线程B多次呼叫GetCurrentLocationWeatherAsync。任务列表现在包含线程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(); 
    } 
} 

孔现在的问题是一类,而不是静态的。这个类本身仍然不是线程安全的,但是如果你总是为一组“天气数据收集”创建一个实例,那么你就不会遇到问题。

请记住,当您有多个线程时,线程安全性只是一个问题。

+0

谢谢你已经开始工作了。我仍然知道这个,所以你可以解释你的意思是代码不是线程安全的,我怎样才能使它更安全 – Ahsan

+0

我添加了一个解释,但请记住,如果你不使用多个线程,你可以简单地使用较高版本。 –

+0

谢谢你,这帮了我很多 – Ahsan

0

任何替代做同样的上述逻辑也将是真正伟大

我以前做这种方式,但无法继续,因为该事件不会返回反序列化objec

//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; 
    // } 
//}