Click here to Skip to main content
Rate this: bad
good
Please Sign up or sign in to vote.
See more: WPF C#4.0 Threading
In My WPF application, I have One Mainwindow with two user controls.
 
My Mainwindow.xaml like this
<Grid Name="MainGrid">
<my:Usercontrol1 HorizontalAlignment="Left" Margin="70,132,0,0" Name="dummy1" VerticalAlignment="Top" />
</Grid>
 
Then my UserControl.Xaml
 
Here I am having one grid contains controls which is connecting to the database, it will take time to load, for that I am using one loadingUserControl like loading rotating image.
 
<Grid Height="300" Width="770" >
    <Grid Height="223" Width="334"  Margin="10,80,346,-20">
 
        <Label Width="90" Height="24" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontFamily="Verdana" FontWeight="Normal" Margin="10,37,6,5" Grid.Column="1">Sql Server</Label>
        <Grid Grid.Column="2" Width="200" removed="White" Height="20" Margin="1,39,20,7">
            <ComboBox VerticalAlignment="Top" HorizontalAlignment="Left" removed="Transparent" Style="{StaticResource StyleForWidth200}" Margin="0,0,0,0" Name="cmbServerName" Width="200" Height="20" FontFamily="Verdana" IsEditable="True" StaysOpenOnEdit="True" ClipToBounds="False">
 
            </ComboBox>
        </Grid>
        <RadioButton Content="Trusted Connection" Grid.Column="2" Height="20" HorizontalAlignment="Left" Name="rbTrustedConnection" VerticalAlignment="Stretch" Width="200" FontFamily="Verdana" FontWeight="Normal" Margin="0,6,0,16" Grid.Row="1" Grid.RowSpan="2" FontSize="10" IsChecked="True" />
        <RadioButton Content="SQL Server Authentication" Grid.Column="2" Grid.Row="2" Height="16" HorizontalAlignment="Left" Name="rbSQLServerAuthentication" VerticalAlignment="Stretch" Width="200" FontFamily="Verdana" FontWeight="Normal" Margin="0,5,0,0" FontSize="10" />
        <Label  Width="90" Height="24" Grid.Row="3" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontFamily="Verdana" FontWeight="Normal" Grid.Column="1" Margin="10,9,6,9">User Name</Label>
        <TextBox Grid.Column="2" Grid.Row="3" Name="txtUserName" Width="200" Height="20" HorizontalAlignment="Left" Text="" FontFamily="Verdana" FontWeight="Normal" Margin="0,11"></TextBox>
        <Label  Width="90" Height="24" Grid.Row="4" HorizontalContentAlignment="Right" VerticalContentAlignment="Center" FontFamily="Verdana" FontWeight="Normal" Grid.Column="1" Margin="10,2,6,2">Password</Label>
        <PasswordBox Grid.Column="2" Grid.Row="4" Width="200" Height="20" HorizontalAlignment="Left" FontFamily="Verdana" Name="txtPwdWord"/>
        <Button Grid.Column="2" Grid.Row="5" Name="btnConnect" Width="70" Height="30" Margin="131,0,20,5" Content="Connect" FontFamily="Verdana" FontWeight="Normal" Focusable="True" Style="{StaticResource NormalStyle11}" Click="btnConnect_Click"></Button>
 
        <my:LoadingControl x:Name="loadingControl1" Margin="0,70,0,0" Visibility="Visible" />
    </Grid>
</Grid>
 
In My code behind UserControl1.cs
here I am using threading
when its loading database, LoadingControl should be rotate,once database loaded loadingControl should be hidden, for that I implemented the following code.
 
here my problem is LoadingControl is not roatating and application get hangs, but when the database loaded lodingcontrol being hidden.
 
can you please figure out what I missed here.
 
private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            BindInstances = new Thread(new ThreadStart(ServerConnection));
            BindInstances.Start();
 
        }
private void ServerConnection()
        {
 
            if (Dispatcher.CheckAccess())
            {
                BindDefaultInstances(); 
                loadingControl1.Visibility = Visibility.Hidden;
            }
            else
            {
                Dispatcher.BeginInvoke(DispatcherPriority.Normal,new Action(ServerConnection));
            }
 
private void BindDefaultInstances()
        {
            DataAccess objIED_DAL = new DataAccess();
          
            DataTable dtInstanceList = new DataTable();
            dtInstanceList = objIED_DAL.GetInstances();
            if (dtInstanceList.Rows.Count > 0)
            {
                foreach (DataRow dr in dtInstanceList.Rows)
                {
                    cmbServerName.Items.Add(dr["ServerName"]);
                }
            }
        }
Posted 6-Mar-13 16:41pm
Edited 6-Mar-13 18:38pm
v4
Comments
Sergey Alexandrovich Kryukov at 6-Mar-13 23:40pm
   
Yes, using the dispatcher is the way to go. Now, what's the problem? Hangs? Where?
I would really advise you to provide more detailed description: what did you try to achieve; description of key points of the code: why and what you expected them to do? what did you observer instead?
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 1

What are you doing?! You are dispatching ServerConnection from ServerConnection! This is your bug.
 
That's it. Just think about it. You probably don't understand what Dispatcher does. You should be doing something nearly opposite: the delegate instance passed to Dispatcher.Invoke or Dispatcher.BeginInvoke should be a quick method showing something in the UI. This method will be actually called in the UI thread.
 
Please see my past answers for more information:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^],
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].
 
(Sorry, some information in my answers is related to System.Windows.Forms, some for WPF, some for both. In you case, ignore anything related to Forms.)
 
—SA
  Permalink  
Comments
D-Kishore at 6-Mar-13 23:58pm
   
Yes Sergey, here I am confused.
 
Actually my problem is when the database loading I want to display like loading..(running image) on the UI.
 
Kindly suggest me.
Sergey Alexandrovich Kryukov at 7-Mar-13 1:49am
   
Do all the database work in a separate thread. (By the way, take a look at my answers on thread wrapper.)
Now, let's say, you create a UI method Show(string data, TextBlock textBlock) { textBlock.Text = data; }.
But you call this method only from UI thread. So you need to invoke it.
 
Make something like Action<string,> action = new Action<string, TextBlock>((data, textBlock) => { Show(data, textBlock); }).
You got the delegate instance to be passed to Dispatcher.Invoke, followed by actual parameters for data and textBlock.
Do it in your "database" thread... Dispatcher.Invoke won't call your Show method in this thread, it will queue it into the UI thread, which has the mechanism to actually call in from the main event loop of the UI thread...
 
—SA
D-Kishore at 7-Mar-13 0:31am
   
Thanks Sergey, find and intimate the bug in my code
Sergey Alexandrovich Kryukov at 7-Mar-13 1:50am
   
You are welcome. I answered now. Are you accepting this answer formally (green button)?
Anyway, your follow-up questions are welcome...
—SA
Shmuel Zang at 7-Mar-13 0:33am
   
5'ed. I added a suggestion for how the code can be fixed.
Sergey Alexandrovich Kryukov at 7-Mar-13 1:51am
   
Thank you Shmuel.
—SA
Rate this: bad
good
Please Sign up or sign in to vote.

Solution 2

As Sergey wrote, your mistake is that you invoke the ServerConnection method in the UI thread. That connection work is done on the UI thread and, that what hangs your UI. Try to change the ServerConnection method to only invoke the UI changes in the UI thread. Something like:

private void ServerConnection()
{
    DataAccess objIED_DAL = new DataAccess();
 
    DataTable dtInstanceList = new DataTable();
    dtInstanceList = objIED_DAL.GetInstances();
 
    if (dtInstanceList.Rows.Count > 0)
    {
        foreach (DataRow dr in dtInstanceList.Rows)
        {
            Dispatcher.BeginInvoke(new Action(() => cmbServerName.Items.Add(dr["ServerName"])));
        }
    }
 
    Dispatcher.BeginInvoke(new Action(() => loadingControl1.Visibility = Visibility.Hidden));
}
  Permalink  
v2
Comments
D-Kishore at 7-Mar-13 0:30am
   
Thank you so much Zang, Now I can see what mistake I did.
mine 5+
Sergey Alexandrovich Kryukov at 7-Mar-13 1:56am
   
Sorry, this code has big problem. I voted 2. Sorry again.
D-Kishore, please don't use it.
This is creation of a thread on a loop! Wow! very bad. And a thread does not have to be created from UI thread. This BeginInvoke is just bad.
You need only one separate thread for all database operations, creating from the very beginning.
This code, too, shows big misunderstanding of invocation. The delegate instance under Invoke or BeginInvoke should only call fast UI methods...
 
Please, read all my referenced past answers, they are very useful...
—SA
Shmuel Zang at 7-Mar-13 2:14am
   
Which thread is created on a loop? ThreadStart is a delegate and, the operation that is preformed is: adding a delegate to the UI queue.
Sergey Alexandrovich Kryukov at 7-Mar-13 2:19am
   
Sorry, my mistake. But why do you use ThreadStart delegate while not creating a thread. I was confused, sorry, but you really have to use delegate System.Action.
—SA
Sergey Alexandrovich Kryukov at 7-Mar-13 2:22am
   
I re-voted by 4, but please fix it; you really need to use System.Action instead.
—SA
Shmuel Zang at 7-Mar-13 2:36am
   
OK. I accept the comment. The solution changed to use Action instead of ThreadStart.
Sergey Alexandrovich Kryukov at 7-Mar-13 2:58am
   
Appreciate it...
—SA
D-Kishore at 7-Mar-13 5:51am
   
Yes you are correct sergey, I also wondered when I saw Threadstart,
 
At the same when I was altering my code I have used Action instead of Threadstart.
 
Thanks Sergey and Zang.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

  Print Answers RSS
0 Marcin Kozub 265
1 Richard MacCutchan 239
2 OriginalGriff 208
3 Sergey Alexandrovich Kryukov 185
4 Praneet Nadkar 167
0 OriginalGriff 7,913
1 Sergey Alexandrovich Kryukov 7,232
2 DamithSL 5,604
3 Manas Bhardwaj 4,986
4 Maciej Los 4,865


Advertise | Privacy | Mobile
Web02 | 2.8.1411023.1 | Last Updated 7 Mar 2013
Copyright © CodeProject, 1999-2014
All Rights Reserved. Terms of Service
Layout: fixed | fluid

CodeProject, 503-250 Ferrand Drive Toronto Ontario, M3C 3G8 Canada +1 416-849-8900 x 100