Click here to Skip to main content
15,880,891 members
Please Sign up or sign in to vote.
3.00/5 (2 votes)
See more:
In My WPF application, I have One Mainwindow with two user controls.

My Mainwindow.xaml like this
XML
<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.

XML
<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.

C#
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
Updated 6-Mar-13 17:38pm
v4
Comments
Sergey Alexandrovich Kryukov 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

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
 
Share this answer
 
Comments
D-Kishore 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 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 7-Mar-13 0:31am    
Thanks Sergey, find and intimate the bug in my code
Sergey Alexandrovich Kryukov 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 7-Mar-13 0:33am    
5'ed. I added a suggestion for how the code can be fixed.

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:


C#
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));
}
 
Share this answer
 
v2
Comments
D-Kishore 7-Mar-13 0:30am    
Thank you so much Zang, Now I can see what mistake I did.
mine 5+
Sergey Alexandrovich Kryukov 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 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 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 7-Mar-13 2:22am    
I re-voted by 4, but please fix it; you really need to use System.Action instead.
—SA

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900