使用Task.Factory返回值以更新UI

时间:2013-01-22 19:17:33

标签: c# multithreading wcf task

这应该很简单,但我找不到足够的术语来搜索......我是C#的新手,我正在尝试创建一个简单的应用程序来编写Web服务的返回。 / p>

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

活动:

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

    }

然后是Threaded方法

    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

3 个答案:

答案 0 :(得分:4)

如果没有了解所有有趣的async/await内容,您可以使用ContinueWithTask方法处理返回的信息。

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技术,您需要使用调度程序来避免获得非法的跨线程访问异常。

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

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));
}

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

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

Windows Store在.ContinueWith(使用CoreDispatcher

内的表达式示例
task =>
{
    var theResultOfYourServiceCall = task.Result;
    tb1.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () => tb1.Text = theResultOfYourServiceCall);
}

答案 1 :(得分:2)

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

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

ps:你也可以使用await&amp; asnet in .net 4.5

答案 2 :(得分:1)

其他人提到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的力量。