C#HttpClient在第二次运行时为空

问题描述 投票:0回答:2

我有问题。我创建了以下ViewModel:

public class TemplateListViewModel
{
    public double WidthHeight { get; set; }

    public ICommand LoadTemplates => new Command(MyHandler);
    public int CurrentTemplateCountReceived;
    public bool HitBottomOfList = false;
    public ObservableCollection<TemplateSource> sourceList { get; set; }


    public TemplateListViewModel()
    {
        CurrentTemplateCountReceived = 0;
        sourceList = new ObservableCollection<TemplateSource>();

        var mainDisplayInfo = DeviceDisplay.MainDisplayInfo;
        var width = mainDisplayInfo.Width;
        var density = mainDisplayInfo.Density;
        var ScaledWidth = width / density;

        WidthHeight = (ScaledWidth / 2);

        loadingTemplates += onLoadingTemplates;
        LoadTemplateList();
    }

    private event EventHandler loadingTemplates = delegate { };

    private Task LoadTemplateList()
    {
        loadingTemplates(this, EventArgs.Empty);
        return null;
    }

    private async void onLoadingTemplates(object sender, EventArgs args)
    {
        if (HitBottomOfList == false)
        {
            List<Template> templateList = await App.RestService.GetTemplates(App.User, CurrentTemplateCountReceived);

            if (templateList != null)
            {
                foreach (var template in templateList)
                {
                    ImageSource source = ImageSource.FromUri(new Uri("http://alexander.vreeswijk.eu/memento/" + App.TemplateSource + template.FileName));
                    TemplateSource templateSource = new TemplateSource { Id = template.Id, Source = source, WidthHeight = WidthHeight, FileName = template.FileName };
                    sourceList.Add(templateSource);
                }

                CurrentTemplateCountReceived = sourceList.Count;
            }
            else
            {
                HitBottomOfList = true;
            }
        }
    }

    bool handling = false;

    public async void MyHandler()
    {
        // already handling an event, ignore the new one
        if (handling) return;

        handling = true;

        await LoadTemplateList();

        handling = false;
    }
}

这是RestService.cs:

HttpClient client;
public string ErrorMessage { get; set; }

public RestService()
{
    client = new HttpClient();
    client.MaxResponseContentBufferSize = 256000;
    client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/x-www-form-urlencoded"));
}

public async Task<List<Template>> GetTemplates(User user, int offset)
{
    var postData = new List<KeyValuePair<string, string>>();
    postData.Add(new KeyValuePair<string, string>("un", user.Username));
    postData.Add(new KeyValuePair<string, string>("pw", user.Password));
    postData.Add(new KeyValuePair<string, string>("offset", offset.ToString()));
    var content = new FormUrlEncodedContent(postData);
    var weburl = "mysite.org/myapp/get_templates.php";
    List<Template> response = await PostResponseTemplates(weburl, content);

    return response;
}

public async Task<List<Template>> PostResponseTemplates(string weburl, FormUrlEncodedContent content)
{
    var response = await client.PostAsync(weburl, content);
    var json = await response.Content.ReadAsStringAsync();

    if (json != "Nothing")
    {
        var jObject = JObject.Parse(json);
        var templatePropery = jObject["Templates"] as JArray;
        List<Template> templateList = new List<Template>();

        foreach (var property in templatePropery)
        {
            List<Template> propertyList = new List<Template>();
            propertyList = JsonConvert.DeserializeObject<List<Template>>(property.ToString());
            templateList.AddRange(propertyList);
        }

        var sourcePropery = (JObject)jObject["Source"];
        foreach (var property in sourcePropery)
        {
            string tempplateSource = property.Value.Value<string>();
            App.TemplateSource = tempplateSource;
        }

        return templateList;
    }
    else
    {
        ErrorMessage = json;
        return default(List<Template>);
    }
}

ICommand LoadTemplates => new Command(MyHandler);在CollectionView几乎到达列表底部时被调用,因此它将获取更多数据。然后,我创建了MyHandler,以检查是否有一个正在忙于网络通话的事件以获取更多数据,因为它多次触发该事件。最后,它执行从我的网页获取数据的onLoadingTemplates

现在首次在构造函数中使用LoadTemplateList();运行时,一切正常,但是在执行它时,就像:await LoadTemplateList();,当触发事件时,它在RestService.cs的以下行崩溃:var response = await client.PostAsync(weburl, content);与错误:

'对象引用未设置为对象的实例。'

有人可以告诉我为什么在触发事件时获取数据时会发生这种情况吗?

c# xamarin xamarin.forms xamarin.android xamarin.ios
2个回答
0
投票

在这里做一些侦探工作。

因为您说过您得到了NullReferenceException

对象引用未设置为对象的实例。

在线

var response = await client.PostAsync(weburl, content);

weburlcontent都不能为空,因为它是先前在GetTemplates方法中创建的,因此只有在前一行中clientnull的可能性仍然存在:如果是这样,您创建客户端后,应确保在客户端中设置以下属性:

httpClient.DefaultRequestHeaders.ConnectionClose = false;
HttpWebRequest.KeepAlive = true;

MSFT文档中有一个不错的post on HttpClient BestPractices

希望这会有所帮助!


0
投票

我可能会押注当前的CollectionView错误。

这不是“第二次被调用”的情况,但是当您更改已加载的边界ObservableCollection时,渲染器会崩溃(并且隐藏了CollectionView的窗口)。

我首先想到的是,它在渲染器中的某个位置正在调用的非UI线程上执行。但是,即使尝试从UI线程修改绑定的ObservableCollection,渲染器仍然会崩溃。

您可以报告这个错误,我没时间做,实际上只是在使用其他自定义的列表视图。

© www.soinside.com 2019 - 2024. All rights reserved.