c# - 在 WPF 应用程序中正确实现任务

标签 c# wpf asynchronous async-await task

我正在寻找一些关于掌握 WPF 中的 Task 的建议,并且想知道是否有人可以查看我的代码并指出我做错了什么?

基本上,应用程序从 UI 获取邮政编码,用于实例化 Task 服务,该服务将获取经度/纬度,可通过实例访问,以用于其他服务或 UI 本身。

我想我可能有一个竞争条件,我希望在 ResultTextBlock.Text 设置为零时纠正它,但是通过实例化我看到了这些值设置。

如有任何关于Task 实现和布线的建议,我们将不胜感激。

服务代码

class PostcodeService
{
    string _result;
    string _postcode;

    HttpResponseMessage _response;        
    RootObject rootObject;

    public double Latitude { get; private set; }
    public double Longitude { get; private set; }        

    public PostcodeService(string postcode)
    {
        this._postcode = postcode;
        rootObject = new RootObject();
    }

    public async Task<string> GetLongLatAsync()
    {        
        using (HttpClient client = new HttpClient())
        {
            client.BaseAddress = new Uri("https://api.postcodes.io/postcodes/" + this._postcode);
            client.DefaultRequestHeaders.Accept.Clear();
            client.DefaultRequestHeaders.Accept.Add(
                new MediaTypeWithQualityHeaderValue("application/json"));  

            try
            {
                _response = await client.GetAsync(client.BaseAddress);
                if(_response.IsSuccessStatusCode)
                {
                    //cast result into model and then set long/lat properties which can then be used in the UI
                    _result = await _response.Content.ReadAsStringAsync();                     

                    rootObject = JsonConvert.DeserializeObject<RootObject>(_result);
                    Longitude = Double.Parse(rootObject.result.longitude.ToString());
                    Latitude =  Double.Parse(rootObject.result.latitude.ToString());
                }                                      
            }
            catch(Exception ex)
            {
                ex.ToString();
            }
        }

        TaskCompletionSource<string> tc = new TaskCompletionSource<string>(_result);

        return tc.ToString();
    }
}

界面代码

private void PostcodeButton_Click(object sender, RoutedEventArgs e)
{
    _clearStatus();

    if (_validatePostcode())
    {
        Task T1 = Task.Factory.StartNew(async () =>
        {
            // get long lat from api
            _postcode = new PostcodeService(PostcodeTextBox.Text);
            await _postcode.GetLongLatAsync();
        });

        //Race condition?
        ResultTextBlock.Text = _postcode.Latitude.ToString();
    }
}

最佳答案

您的GetLongLatAsync() 方法应该返回一个字符串:

public async Task<string> GetLongLatAsync()
{
    using (HttpClient client = new HttpClient())
    {
        client.BaseAddress = new Uri("https://api.postcodes.io/postcodes/" + this._postcode);
        client.DefaultRequestHeaders.Accept.Clear();
        client.DefaultRequestHeaders.Accept.Add(
            new MediaTypeWithQualityHeaderValue("application/json"));

        _response = await client.GetAsync(client.BaseAddress);
        string result = null;
        if (_response.IsSuccessStatusCode)
        {
            //cast result into model and then set long/lat properties which can then be used in the UI
            result = await _response.Content.ReadAsStringAsync();

            rootObject = JsonConvert.DeserializeObject<RootObject>(_result);
            Longitude = Double.Parse(rootObject.result.longitude.ToString());
            Latitude = Double.Parse(rootObject.result.latitude.ToString());
        }
        return result;
    }
}

...您只需在 UI 中等待 GetLongLatAsync():

private async void PostcodeButton_Click(object sender, RoutedEventArgs e)
{
    _clearStatus();
    if (_validatePostcode())
    {
        // get long lat from api
        _postcode = new PostcodeService(PostcodeTextBox.Text);
        string result = await _postcode.GetLongLatAsync();
        ResultTextBlock.Text = result.ToString();
    }
}

您不需要使用 TaskCompletionSource 也不需要启动新的 Task 来调用异步方法。

关于c# - 在 WPF 应用程序中正确实现任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55261660/

相关文章:

c# - 发现同一依赖程序集的版本之间存在冲突

c# - 我可以在 RichTextBox 中插入一个带有进度条的按钮吗

c# - 显式打开时上下文菜单不显示绑定(bind)项目(通过 ContextMenu.IsOpen)

c# - 枚举 JumpList 最近的文件?

.net - 如何根据 WPF 中的 bool 属性设置背景颜色

java - 与 RxJava 并行处理 IO 密集型任务列表

java - 在 Android 中访问字符串数组中的最后一个 "number"元素

c# - 是否有任何好的替代结构用于使用内部开关盒?

c# - 覆盖 ASP.Net Core 中的 415 响应

javascript - 异步加载到 body 中的 JS 使浏览器保持在 "loading"模式