ObjectDisposedException:CancellationTokenSource已被释放

时间:2016-06-24 09:46:05

标签: c# ios xamarin.ios xamarin.forms

我开始在MacBook Pro上使用Xamarin Studio开发Xamarin.Forms。我构建了一个应用程序,其目的是查询PrestaShop网站,检索产品并显示它们。

在将应用程序部署到Android时,我在Marshmallow下面的版本遇到了一些问题,但是我解决了它们,所以我不会在这里描述它们。

将应用程序部署到iOS(模拟器)时,我仍然遇到严重问题。应用程序运行,但是当我单击按钮以检索数据时,它会崩溃,给我一个System.ObjectDisposedException,其消息为" CancellationTokenSource已被处理"。我将在此粘贴相关的源代码:

async void button1_Click(object sender, System.EventArgs e)
{
    try
    {
        HttpClientHandler hnd = new HttpClientHandler();
        hnd.Credentials = new NetworkCredential("[apikey]", "");
        string res;
        using (var client = new HttpClient(hnd))
        {
            var responseText = await client.GetStringAsync("[endpoint]/products");
            using (MemoryStream stream = new MemoryStream())
            using (StreamWriter writer = new StreamWriter(stream))
            {
                writer.Write(responseText.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty));
                writer.Flush();
                stream.Position = 0;
                XDocument doc = XDocument.Load(stream);
                res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true);
            }
            var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(res);
            //Result.Text = data["products"].GetType().ToString() + Result.Text;
            Func<string, Task> creator_method = async (string id) =>
            {
                try
                {
                    var responseProd = await client.GetStringAsync($"[endpoint]/products/{id}"); // AT THIS ROW THE EXCEPTION IS RAISED!!!
                    using (MemoryStream stream = new MemoryStream())
                    using (StreamWriter writer = new StreamWriter(stream))
                    {
                        writer.Write(responseProd.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty));
                        writer.Flush();
                        stream.Position = 0;
                        XDocument doc = XDocument.Load(stream);
                        res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true);
                    }
                    var product_rawData = JsonConvert.DeserializeObject<Dictionary<string, object>>(res);
                    var productData = (JObject)product_rawData["product"];
                    try
                    {
                        views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), productData["id_default_image"]["@xlink:href"].ToString()));
                    }
                    catch (NullReferenceException nre)
                    {
                        views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), ""));
                    }
                }
                catch (Exception gex) { throw; }
            };
            foreach (var product in ((JObject)data["products"])["product"])
                try
                {
                    Device.BeginInvokeOnMainThread(async () => { await creator_method.Invoke(product["@id"].ToString()); });
                }
                catch (TaskCanceledException tce) { continue; }
                catch (WebException we) { continue;}
        }
    }
    catch (HttpRequestException ex)
    {
        Result.Text = ex.Message;
    }
}

我怎么能解决这个问题?

3 个答案:

答案 0 :(得分:5)

  

&#34; CancellationTokenSource已被处理&#34;

第一次CancellationToken来电似乎已经消耗了client.GetStringAsync() using

如何解决此问题
我建议将你的第二个电话放在自己的using块中,以避免这种情况。

以下是您的代码现在应该是什么样子,并使用第二个async void button1_Click(object sender, System.EventArgs e) { try { HttpClientHandler hnd = new HttpClientHandler(); hnd.Credentials = new NetworkCredential("[apikey]", ""); string res; using (var client = new HttpClient(hnd)) { var responseText = await client.GetStringAsync("[endpoint]/products"); using (MemoryStream stream = new MemoryStream()) using (StreamWriter writer = new StreamWriter(stream)) { writer.Write(responseText.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty)); writer.Flush(); stream.Position = 0; XDocument doc = XDocument.Load(stream); res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true); } var data = JsonConvert.DeserializeObject<Dictionary<string, object>>(res); //Result.Text = data["products"].GetType().ToString() + Result.Text; Func<string, Task> creator_method = async (string id) => { try { using (var newClient = new HttpClient(hnd)) // Create a new client to avoid your other one's token being consumed { var responseProd = await newClient.GetStringAsync($"[endpoint]/products/{id}"); using (MemoryStream stream = new MemoryStream()) using (StreamWriter writer = new StreamWriter(stream)) { writer.Write(responseProd.Replace("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n", string.Empty)); writer.Flush(); stream.Position = 0; XDocument doc = XDocument.Load(stream); res = JsonConvert.SerializeXNode(doc, Formatting.Indented, true); } var product_rawData = JsonConvert.DeserializeObject<Dictionary<string, object>>(res); var productData = (JObject)product_rawData["product"]; try { views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), productData["id_default_image"]["@xlink:href"].ToString())); } catch (NullReferenceException nre) { views.Children.Add(new ProductXaml(productData["name"]["language"]["#cdata-section"].ToString(), float.Parse(productData["price"]["#cdata-section"].ToString().Replace('.', ',')), "")); } } } catch (Exception gex) { throw; } }; foreach (var product in ((JObject)data["products"])["product"]) try { Device.BeginInvokeOnMainThread(async () => { await creator_method.Invoke(product["@id"].ToString()); }); } catch (TaskCanceledException tce) { continue; } catch (WebException we) { continue;} } } catch (HttpRequestException ex) { Result.Text = ex.Message; } } 声明:

QuerySet.extra()

希望这有帮助! :)

答案 1 :(得分:0)

我遇到了同样的问题,我使用单个httpclient来处理所有api请求。

private static HttpClient httpClient;

public static HttpClient GetHttpClient()
{
    if (httpClient == null)
    {
        httpClient = new HttpClient()
        {
            BaseAddress = new Uri(BaseUrl)
        };
        httpClient.DefaultRequestHeaders.Accept.Clear();
        httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
    }

    return httpClient;
}
  

看来你正在使用(var client = new HttpClient())...&#39; s   CancellationToken已被第一个消费   client.GetStringAsync()调用。

杰夫的回答我删除了静态httpclient,现在为所有请求创建了一个新的httpclient,它解决了我的问题。

public static HttpClient GetHttpClient()
{
    HttpClient httpClient = new HttpClient()
    {
        BaseAddress = new Uri(BaseUrl)
    };
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

    return httpClient;
}

答案 2 :(得分:0)

像这样创建HttpClient的新实例

public static HttpClient GetHttpClient()
{
    HttpClient httpClient = new HttpClient()
    {
        BaseAddress = new Uri(BaseUrl)
    };
    httpClient.DefaultRequestHeaders.Accept.Clear();
    httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));

return httpClient;

}