【问题标题】:Returning value with Task.Factory to Update the UI使用 Task.Factory 返回值以更新 UI
【发布时间】:2013-01-22 19:17:33
【问题描述】:

这应该很容易,但我找不到合适的术语来搜索...好吧,我是 C# 新手,我正在尝试制作一个简单的应用程序来编写 web 服务的返回。

我遇到了使用线程的需要...向线程传递参数相当容易,我找不到从 Threaded 方法返回并更新我的 UI 以显示结果的方法(实际上没有现在的实际结果)

事件:

    private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
    {
        minhaSigla = Sigla.Text;
        Task.Factory.StartNew(() => GetQuoteAndUpdateText(minhaSigla));
        tb1.Text = "UIElement-TO-UPDATE";

    }

然后是线程方法

    private string GetQuoteAndUpdateText(string sign)
    {
        string SoapEnvelope = "";
        SoapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
        SoapEnvelope += "<soap:Envelope ";
        SoapEnvelope += "xmlns:xsi = \"http://www.w3.org/2001/XMLSchema-instance\" ";
        SoapEnvelope += "xmlns:xsd= \"http://www.w3.org/2001/XMLSchema\" ";
        SoapEnvelope += "xmlns:soap= \"http://schemas.xmlsoap.org/soap/envelope/\">";
        SoapEnvelope += "<soap:Body>";
        SoapEnvelope += "   <GetQuote xmlns=\"http://www.webserviceX.NET/\"> ";
        SoapEnvelope += "       <symbol>" + sign + "</symbol> ";
        SoapEnvelope += "   </GetQuote> ";
        SoapEnvelope += "</soap:Body>";
        SoapEnvelope += "</soap:Envelope>";

        EndpointAddress endpoint = new EndpointAddress("http://www.webservicex.net/stockquote.asmx");
        BasicHttpBinding basicbinding = new BasicHttpBinding();
        basicbinding.SendTimeout = new TimeSpan(3000000000);
        basicbinding.OpenTimeout = new TimeSpan(3000000000);

        stockbyname.StockQuoteSoapClient sbn = new stockbyname.StockQuoteSoapClient(basicbinding, endpoint);

        XmlDocument xmlDocument = new XmlDocument();
        return sbn.GetQuote(SoapEnvelope);
    }

任何信息都将不胜感激,甚至是关于我的代码有多糟糕的信息:P

【问题讨论】:

    标签: c# multithreading wcf task


    【解决方案1】:

    无需深入了解async/await 的所有乐趣,您可以使用TaskContinueWith 方法来处理返回的信息。

    private void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
    {
        minhaSigla = Sigla.Text;
        var quoteGetterTask = Task.Factory.StartNew(() => GetQuoteAndUpdateText(minhaSigla));
        quoteGetterTask.ContinueWith(task => 
        {
            var theResultOfYourServiceCall = task.Result;
            //You'll need to use a dispatcher here to set the value of the text box (see below)
            tb1.Text = theResultOfYourServiceCall;     //"UIElement-TO-UPDATE";
        });
    }
    

    正如我在上面的代码示例中提到的,根据您使用的 UI 技术,您需要使用调度程序来避免出现非法的跨线程访问异常。

    .ContinueWith内的表达式的WinForms示例(使用ControlInvoke方法)

    task =>
    {
        var theResultOfYourServiceCall = task.Result;
        tb1.Invoke(new Action(() => tb1.Text = theResultOfYourServiceCall));
    }
    

    .ContinueWith里面的表达式的WPF例子(使用WPF的Dispatcher

    task =>
    {
        var theResultOfYourServiceCall = task.Result;
        tb1.Dispatcher.Invoke(DispatcherPriority.Normal, 
                              new Action(() => tb1.Text = theResultOfYourServiceCall));
    }
    

    .ContinueWith 内的表达式的 Silverlight/Windows Phone 示例(使用 Silverlight 的 Dispatcher

    task =>
    {
        var theResultOfYourServiceCall = task.Result;
        tb1.Dispatcher.BeginInvoke(() => tb1.Text = theResultOfYourServiceCall);
    }
    

    .ContinueWith 内表达式的 Windows Store 示例(使用 CoreDispatcher

    task =>
    {
        var theResultOfYourServiceCall = task.Result;
        tb1.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => tb1.Text = theResultOfYourServiceCall);
    }
    

    【讨论】:

      【解决方案2】:

      更常见的是,您需要 UI 线程上的任务,因为这可以让您更新您的控件。

      Task<string>.Factory.StartNew(() => GetQuoteAndUpdateText(minhaSigla)).ContinueWith(s=>  tb1.Text = s, 
      TaskScheduler.FromCurrentSynchronizationContext());
      

      ps : 你也可以在 .net 4.5 中使用 await & async

      【讨论】:

        【解决方案3】:

        其他人提到了async/await,但这里有一个简单的例子:

        private async void TextBox_TextChanged_1(object sender, TextChangedEventArgs e)
        {
            minhaSigla = Sigla.Text;
            string result = await GetQuoteAndUpdateTextAsync(minhaSigla);
            tb1.Text = "UIElement-TO-UPDATE";
        }
        
        private Task<string> GetQuoteAndUpdateTextAsync(string sign)
        {
            string SoapEnvelope = "";
            SoapEnvelope = "<?xml version=\"1.0\" encoding=\"utf-8\"?>";
            SoapEnvelope += "<soap:Envelope ";
            SoapEnvelope += "xmlns:xsi = \"http://www.w3.org/2001/XMLSchema-instance\" ";
            SoapEnvelope += "xmlns:xsd= \"http://www.w3.org/2001/XMLSchema\" ";
            SoapEnvelope += "xmlns:soap= \"http://schemas.xmlsoap.org/soap/envelope/\">";
            SoapEnvelope += "<soap:Body>";
            SoapEnvelope += "   <GetQuote xmlns=\"http://www.webserviceX.NET/\"> ";
            SoapEnvelope += "       <symbol>" + sign + "</symbol> ";
            SoapEnvelope += "   </GetQuote> ";
            SoapEnvelope += "</soap:Body>";
            SoapEnvelope += "</soap:Envelope>";
        
            EndpointAddress endpoint = new EndpointAddress("http://www.webservicex.net/stockquote.asmx");
            BasicHttpBinding basicbinding = new BasicHttpBinding();
            basicbinding.SendTimeout = new TimeSpan(3000000000);
            basicbinding.OpenTimeout = new TimeSpan(3000000000);
        
            stockbyname.StockQuoteSoapClient sbn = new stockbyname.StockQuoteSoapClient(basicbinding, endpoint);
        
            XmlDocument xmlDocument = new XmlDocument();
            return sbn.GetQuoteAsync(SoapEnvelope);
        }
        

        请注意它与您现有的方法有多么相似。这就是async 的力量。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-07-27
          • 1970-01-01
          • 2021-02-09
          • 1970-01-01
          • 2022-01-20
          • 2013-04-20
          相关资源
          最近更新 更多