如何管理线程来更新GUI?

时间:2014-01-15 07:38:09

标签: c# wpf multithreading user-interface refresh

首先 - 请原谅我糟糕的发音。 我正在为excelsheet编写一个wpf验证器,虽然这个程序从谷歌获取信息,它应该显示进度条上的进度。我在网上看过很多关于多线程和后台工作的文章,但我认为没有什么能真正帮助我。

这是我的GUI

<Window x:Class="DatenValidierung.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="570" Width="825" ResizeMode="NoResize">
    <Grid Background="Black">
        <Button Foreground="White" Background="Black" Name="exit" Content="Exit" HorizontalAlignment="Left" Margin="714,484,0,0" VerticalAlignment="Top" Width="94" Click="exit_Click" Height="27"/>
        <Button Foreground="White" Background="Black" Name="open" Content="Excel öffnen" HorizontalAlignment="Left" Margin="10,460,0,0" VerticalAlignment="Top" Width="88" Click="open_Click" />
        <DataGrid Name="dg1" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="445" Width="798" AutoGenerateColumns="False" IsReadOnly="True">
            <DataGrid.Columns>
                <DataGridTextColumn Binding="{Binding SubCategory}" Header="Kat" Width="90" />
                <DataGridTextColumn Binding="{Binding Title}" Header="Title" Width="80" />
                <DataGridTextColumn Binding="{Binding InfoText}" Header="Info" Width="80" />
                <DataGridTextColumn Binding="{Binding Domain}" Header="Domain" Width="60" />
                <DataGridTextColumn Binding="{Binding City}" Header="City" Width="50" />
                <DataGridTextColumn Binding="{Binding Zipcode}" Header="Zip" Width="50" />
                <DataGridTextColumn Binding="{Binding Longitude}" Header="Long" Width="50" />
                <DataGridTextColumn Binding="{Binding Latitude}" Header="Lat" Width="50" />
                <DataGridTextColumn Binding="{Binding Telefon}" Header="Tel" Width="50" />
                <DataGridTextColumn Binding="{Binding Mail}" Header="Mail" Width="50" />
                <DataGridTextColumn Binding="{Binding Address}" Header="Adresse" Width="50" />
            </DataGrid.Columns>
        </DataGrid>
        <Button Content="Hochladen" Background="Black" Foreground="White" Name="upload" Click="upload_Click" HorizontalAlignment="Left" Margin="10,508,0,0" VerticalAlignment="Top" Width="88"/>
        <Button Content="google-Daten" Name="check" Background="Black" Foreground="White" HorizontalAlignment="Left" Margin="10,484,0,0" VerticalAlignment="Top" Width="88"  Click="check_Click"/>
        <ProgressBar Value="{Binding Path=ProgressValue}" HorizontalAlignment="Left" Height="24" Margin="270,460,0,0" VerticalAlignment="Top" Width="200" Name="pb1"/>
        <Label Name="progressLabel" Foreground="White" TextBlock.TextAlignment="Center" Content="" HorizontalAlignment="Left" Margin="320,489,0,0" VerticalAlignment="Top" Width="100"/>

    </Grid>
</Window>

这是我的CodeBehind

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Windows;
    using System.Windows.Forms;
    using System.Windows.Controls;
    using System.Windows.Data;
    using System.Windows.Documents;
    using System.Windows.Input;
    using System.Windows.Media;
    using System.Windows.Media.Imaging;
    using System.Windows.Navigation;
    using System.Windows.Shapes;
    using Excel = Microsoft.Office.Interop.Excel;
    using System.Data.OleDb;
    using System.Data;
    using System.Globalization;
    using System.ComponentModel;
    using System.Threading;
    using System.Net;
    using System.Xml.Linq;
    using DatenValidierung.ServiceReference1;



    namespace DatenValidierung
    {
        public partial class MainWindow : Window
        {
            int progressCounter = 0;
            List<Location> locationList = new List<Location>();

            public MainWindow()
            {
                InitializeComponent();           
            }

            double progressValue;
            public double ProgressValue
            {
                get { return progressValue; }
                set
                {
                    if (progressValue != value)
                    {
                        progressValue = value;
                        OnPropertyChanged("ProgressValue");
                    }
                }
            }

            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged(string property_name)
            {
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs(property_name));
            }   

            public static DataTable ReadExcelData(string filePath)
            {
                System.Data.DataTable dtExcel = new System.Data.DataTable();
                dtExcel.TableName = "MyExcelData";
                bool hasHeaders = false;
                string strConn = string.Empty;
                string HDR = hasHeaders ? "Yes" : "No";
                if (filePath.Substring(filePath.LastIndexOf('.')).ToLower() == ".xlsx")
                {
                    strConn = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + filePath + ";Extended Properties=\"Excel 12.0;HDR=" + HDR + ";IMEX=0\"";
                }
                else
                {
                    strConn = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" + filePath + ";Extended Properties=\"Excel 8.0;HDR=" + HDR + ";IMEX=0\"";
                }
                //string SourceConstr = @"Provider=Microsoft.ACE.OLEDB.12.0;Data Source='MyExcelFilePath';Extended Properties= 'Excel 8.0;HDR=Yes;IMEX=1'";
                OleDbConnection con = new OleDbConnection(strConn);
                con.Open();
                DataTable schemaTable = con.GetOleDbSchemaTable(OleDbSchemaGuid.Tables, new object[] { null, null, null, "TABLE" });
                DataRow schemaRow = schemaTable.Rows[0];
                string sheet = schemaRow["TABLE_NAME"].ToString();
                string query = "SELECT  * FROM [" + sheet + "]";
                OleDbDataAdapter data = new OleDbDataAdapter(query, con);
                data.Fill(dtExcel);

                return dtExcel;
            }

            private void open_Click(object sender, RoutedEventArgs e)
            {
                var dataFromExcel = new DataTable();
                string ausgabeTemp = String.Empty;
                OpenFileDialog BrowserFileDialog = new OpenFileDialog();
                BrowserFileDialog.Title = "";
                BrowserFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);            
                BrowserFileDialog.FilterIndex = 1;
                BrowserFileDialog.RestoreDirectory = true;
                if (BrowserFileDialog.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                {                
                     dataFromExcel = ReadExcelData(BrowserFileDialog.FileName);
                }

                var liste = dataFromExcel.AsEnumerable().ToList();

                int k = 0;
                for (int i = 0; i < liste.Count; i++)
                {                
                    Location loc = new Location();
                    loc.SubCategory = liste[k].ItemArray[0].ToString();
                    loc.City = liste[k].ItemArray[1].ToString();
                    loc.Zipcode = liste[k].ItemArray[2].ToString();
                    loc.Address = liste[k].ItemArray[3].ToString();
                    loc.Telefon = liste[k].ItemArray[4].ToString();
                    loc.Mail = liste[k].ItemArray[5].ToString();
                    loc.Domain = liste[k].ItemArray[6].ToString();
                    loc.SubCategory = liste[k].ItemArray[7].ToString();
                    loc.InfoText = liste[k].ItemArray[8].ToString();
                    locationList.Add(loc);
                    k++;
                }
                pb1.Maximum = k;
                pb1.Minimum = 0;
                var fred = new Thread(updateProgressBar);
                fred.IsBackground = true;
                fred.Start();
                FormatList(locationList);

            }

            public void updateProgressBar() 
            {
                ProgressValue = ((double)progressCounter * 100) / locationList.Count ;
                progressLabel.Content = ProgressValue + " / 100";
            }

            public List<Location> FormatList(List<Location> locationList)
            {


                var locList = locationList;
                locList = FormatLocationForDB(locList);
                for (int i = 0; i < locList.Count; i++)
                {
                    if (locList[i].Latitude == 0 || locList[0].Longitude == 0)
                    {
                        locList[i] = GetSingleFormatForDB(locList[i]);
                    }
                }
                return locList;
            }

            public List<Location> FormatLocationForDB(object o)
            {
                progressCounter = 0;
                var locList = new List<Location>();
                foreach (Location currentLocation in locationList)
                {
                    Thread.Sleep(50);
                    // System.Threading.Thread.Sleep(200);
                    string address = currentLocation.Address + ", " + currentLocation.City;
                    var requestUri = string.Format("http://maps.googleapis.com/maps/api/geocode/xml?address={0}&sensor=false", Uri.EscapeDataString(address));
                    var request = WebRequest.Create(requestUri);
                    var response = request.GetResponse();
                    var xdoc = XDocument.Load(response.GetResponseStream());


                    try
                    {
                        var result = xdoc.Element("GeocodeResponse").Element("result");
                        var locationElement = result.Element("geometry").Element("location");
                        currentLocation.Latitude = (float)(locationElement.Element("lat"));
                        currentLocation.Longitude = (float)(locationElement.Element("lng"));
                    }
                    catch (Exception x)
                    {

                    }
                    dg1.Items.Add(currentLocation);
                    dg1.InvalidateVisual();
                    progressCounter++;               
                    locList.Add(currentLocation);
                }
                return locList;

            }

            public Location GetSingleFormatForDB(Location location)
            {
                string address = location.Address + ", " + location.City;
                var requestUri = string.Format("http://maps.googleapis.com/maps/api/geocode/xml?address={0}&sensor=false", Uri.EscapeDataString(address));
                var request = WebRequest.Create(requestUri);
                var response = request.GetResponse();
                var xdoc = XDocument.Load(response.GetResponseStream());
                try
                {
                    var result = xdoc.Element("GeocodeResponse").Element("result");
                    var locationElement = result.Element("geometry").Element("location");
                    location.Latitude = (float)(locationElement.Element("lat"));
                    location.Longitude = (float)(locationElement.Element("lng"));
                }
                catch (Exception x)
                {

                }
                return location;
            }

            public static void InsertLocationListToDB(Location location)
            {
                Service1Client wcf = new Service1Client();
                try
                {
                    wcf.ClientCredentials.UserName.UserName = "admin2";
                    wcf.ClientCredentials.UserName.Password = "123test123!";
                    wcf.AddLocationFromListAsync(
                        location.SubCategory,
                        location.Title,
                        location.InfoText,
                        location.Domain,
                        location.City,
                        location.Zipcode,
                        (float)location.Longitude,
                        (float)location.Latitude,
                        location.Telefon,
                        location.Mail,
                        location.Address
                        );
                }
                catch (Exception x)
                {
                }
            }

            private void upload_Click(object sender, RoutedEventArgs e)
            {
                if (locationList.Count > 0 || locationList != null)
                {
                    dg1.Items.Clear();
                    foreach (Location l in locationList)
                    {
                        if (l.Latitude != 0 && l.Longitude != 0)
                        {
                            locationList.Remove(l);
                        }
                        dg1.Items.Add(l);
                    }
                }

            }

            private void check_Click(object sender, RoutedEventArgs e)
            {
                locationList = FormatLocationForDB(locationList);
            }

            private void exit_Click(object sender, RoutedEventArgs e)
            {
                this.Close();
            }
        }

}

我试图在线程中管理progressbarvalue,但根本没有任何事情发生。程序结束时,该值仍为0。有人能帮助我吗?有一个容易出错的错误吗?或者我应该尝试一些像背景工作者那样的事情(我觉得它看起来很相似)。

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

private double _progressLabelContent;

public double ProgressLabelContent
{
get {return _progressLabelContent; }
set { _progressLabelContent=value; OnPropertyChanged("ProgressLabelContent"); }
}

 public void updateProgressBar()
 {
     Application.Current.Dispatcher.Invoke(delegate
     {
         ProgressValue = ((double)progressCounter * 100) / locationList.Count;
         ProgressLabelContent = ProgressValue + " / 100";
     });

 }  

XAML

<Label Content={Binding Path=ProgressLabelContent}  Foreground="White" TextBlock.TextAlignment="Center" Content="" HorizontalAlignment="Left" Margin="320,489,0,0" VerticalAlignment="Top" Width="100"/>