2015-05-24 68 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; 
    // } 
//}