1

间歇性地,Encoding.ASCII.GetString 调用失败并出现异常,该异常会转义所有就地的 catch 块并冻结应用程序。

private string ExecuteRequest(Uri url, KeyValuePair<string, string>[] postItems = null)
{
    var data = new byte[0];
    var response = new byte[0];
    using (var client = new WebClient())
    {
        if (postItems != null && postItems.Count() > 0)
        {
            string dataString = string.Join("&", postItems.Select(
                                    item => string.Format("{0}={1}", item.Key, item.Value)).ToArray());
            data = new ASCIIEncoding().GetBytes(dataString);
        }
        response = client.UploadData(url, "POST", data);
        Android.Util.Log.Info("info", "response from the post received. about to get string");
        client.Dispose();
    }
    try
    {
        return Encoding.ASCII.GetString(response);
    }
    catch (Exception ex)
    {
        Android.Util.Log.Info("info", 
            "Encoding.ASCII.GetString Exception : {0}, {1}", ex.Message, ex.StackTrace);
        throw new ApplicationException("UnRecoverable. Abort");
    }            
}

我得到的 StackTrace 是

I/sssvida (10960): response from the post received. about to get string
I/mono    (10960): Stacktrace:
I/mono    (10960):
I/mono    (10960):   at System.Text.ASCIIEncoding.GetString (byte[],int,int) <0x000cb>
I/mono    (10960):   at System.Text.Encoding.GetString (byte[]) <0x00037>
I/mono    (10960):   at ServiceRequest.ExecuteRequest (System.Uri,System.Collections.Generic.KeyValuePair`2<string, string>[]) <0x0026b>

间歇性地,我得到一个不寻常的堆栈跟踪,如下所示

I/mono    ( 9817): Stacktrace:
I/mono    ( 9817):
F/        ( 9817): * Assertion at ../../../../mono/mini/mini-exceptions.c:472, condition `class' not met
D/dalvikvm(  220): GC_EXPLICIT freed 1K, 35% free 17547K/26759K, paused 3ms+3ms

响应是 json 数据,范围在 1 - 4 mb 之间。

请帮忙。谢谢!!!!

编辑 2:我更新了代码以使用 UploadString 而不是 UploadData 并且间歇性地我得到这个:

I/mono    (15065): Stacktrace:
I/mono    (15065):
I/mono    (15065):   at string.CreateString (char[]) <0x0004b>
I/mono    (15065):   at (wrapper managed-to-managed) string..ctor (char[]) <0xffffffff>
I/mono    (15065):   at System.Text.Encoding.GetString (byte[],int,int) <0x00043>
I/mono    (15065):   at System.Text.UTF8Encoding.GetString (byte[],int,int) <0x0002b>
I/mono    (15065):   at System.Text.Encoding.GetString (byte[]) <0x00037>
I/mono    (15065):   at System.Net.WebClient.UploadString (System.Uri,string,string) <0x0007f>
I/mono    (15065):   at (wrapper remoting-invoke-with-check) System.Net.WebClient.UploadString (System.Uri,string,string) <0xffffffff>
4

2 回答 2

0

分页数据和分块下载可能是这里唯一正确且可扩展/稳健的解决方案。

目前,下面的代码还没有爆炸,可能是我还没有达到临界点。但这是我第一次在设备上进行分块。Encoding.ASCII.GetString 不会在下面的代码中爆炸。

private string ExecuteRequest(Uri url, KeyValuePair<string, string>[] postItems = null)
{
    var data = new byte[0];
    var response = new byte[0];
    ///switched to WebClient because
    /// http://stackoverflow.com/questions/8167726/monodroid-intermittent-failure-when-reading-a-large-json-string-from-web-servi
    using (var client = new WebClient())
    {
        if (postItems != null && postItems.Count() > 0)
        {
            string dataString = string.Join("&", postItems.Select(
                                    item => string.Format("{0}={1}", item.Key, item.Value)).ToArray());
            data = new ASCIIEncoding().GetBytes(dataString);
        }
        response = client.UploadData(url, "POST", data);
        Android.Util.Log.Info("info", "response from the post received. about to get string");
        client.Dispose();
    }
    try
    {
        Android.Util.Log.Info("info", "response size : {0}", response.Length);
        var chunkSize = 50000;
        if (response.Length > chunkSize)
        {
            var returnValue = new StringBuilder();
            for (int i = 0; i < response.Length; i+= chunkSize)
            {                        
                int end = (i + chunkSize) > response.Length ? response.Length - i : chunkSize;
                returnValue.Append(Encoding.ASCII.GetString(response, i, end));
                Android.Util.Log.Info("info", "added a chunk from {0} to {1}", i, end);
            }
            return returnValue.ToString();
        }
        return Encoding.ASCII.GetString(response);
    }
    catch (Exception ex)
    {
        Android.Util.Log.Info("info", 
            "Encoding.ASCII.GetString Exception : {0}, {1}", ex.Message, ex.StackTrace);
        throw new ApplicationException("UnRecoverable. Abort");
    }            
}
于 2011-11-21T22:05:14.743 回答
0

首先,请按照 Rolf 在评论中的要求填写错误报告。第二个堆栈跟踪是不应该发生的崩溃。

至于第一个问题,是否有任何理由不使用(其中一个重载)WebClient.UploadString

该方法将负责编码,确保 HTTP 请求标头匹配,对请求和响应进行编码……这还将返回一个字符串(为您提供更少的代码:-)。

否则,您最终可能会得到一个字符串(除非您在此代码之前有其他验证),该字符串无法以 ASCII 编码,并且会导致异常(遗憾的是,我们只有堆栈跟踪,而不是抛出的确切异常来确认这一点)。

于 2011-11-21T20:27:52.173 回答