当前位置: 动力学知识库 > 问答 > 编程问答 >

c# - Updating UI thread from another thread only works on some values

问题描述:

I have an app which does some downloading in another thread. The size of the file is too large to download in the UI thread as it freezes the UI..

Initialize thread:

Thread oThread = new Thread(new ThreadStart(parse));

Inside the "parse" async method:

(Reader and Article are methods of the ReadSharp library)

source.Foreground = new SolidColorBrush(Colors.Black);

title.Foreground = new SolidColorBrush(Colors.Black);

tt.Opacity = 0;

Reader reader = new Reader();

Article article;

article = await reader.Read(new Uri(ids));

tt.Opacity = 0.5;

source.Foreground = new SolidColorBrush(Colors.White);

title.Foreground = new SolidColorBrush(Colors.White);

featuredimg.Dispatcher.BeginInvoke(

(Action)(() => { featuredimg.Source = new BitmapImage(new Uri(article.FrontImage.ToString(), UriKind.Absolute)); }));

Everything works fine other then the "featuredimg.Source" part of the code. It simply does not update. I tried using the dispatcher with no different results.

网友答案:

I don't see anything fundamentally wrong with the code you posted. So if there's a problem, it's likely in another part of the code, which you did not include here. As always, it's better to provide a complete and concise code example. See http://stackoverflow.com/help/mcve.

If you are expecting that when your oThread object completes that the bitmap will be initialized, then that expectation is incorrect. The thread itself will exit as soon as the parse() method reaches the await reader.Read(new Uri(ids)); statement.

All that said, you can at least improve on what you seem to have now. The use of an explicit Thread object is unnecessary here and just gets in the way. Instead, you should have something like this:

async void someEventHandler(object sender, RoutedEventArgs e)
{
    await parse();
}

async Task parse()
{
    source.Foreground = new SolidColorBrush(Colors.Black);
    title.Foreground = new SolidColorBrush(Colors.Black);
    tt.Opacity = 0;
    Reader reader = new Reader();
    Article article;
    article = await reader.Read(new Uri(ids));
    tt.Opacity = 0.5;
    source.Foreground = new SolidColorBrush(Colors.White);
    title.Foreground = new SolidColorBrush(Colors.White);

    featuredimg.Source = new BitmapImage(
        new Uri(article.FrontImage.ToString(), UriKind.Absolute));
}

In other words, there's no need to call Dispatcher.BeginInvoke() when you're dealing with the async method, assuming the operation is initiated on the UI thread. You simply await as needed for the Read() method to complete, and let everything else happen on the UI thread normally.

Variations on the above include simply calling parse() as "fire and forget":

void someEventHandler(object sender, RoutedEventArgs e)
{
    var _ = parse();
}

Or having the parse() method actually return the Article object and letting the event handler update the bitmap:

async void someEventHandler(object sender, RoutedEventArgs e)
{
    Article article = await parse();

    featuredimg.Source = new BitmapImage(
        new Uri(article.FrontImage.ToString(), UriKind.Absolute));
}

async Task<Article> parse()
{
    source.Foreground = new SolidColorBrush(Colors.Black);
    title.Foreground = new SolidColorBrush(Colors.Black);
    tt.Opacity = 0;
    Reader reader = new Reader();
    Article article;
    article = await reader.Read(new Uri(ids));
    tt.Opacity = 0.5;
    source.Foreground = new SolidColorBrush(Colors.White);
    title.Foreground = new SolidColorBrush(Colors.White);

    return article;
}

You can rearrange the code to put UI-related operations in the event handler or the parse() method to suit your preference.

分享给朋友:
您可能感兴趣的文章:
随机阅读: