Click here to Skip to main content
15,906,567 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi, I'm currently writing an application that controls concert lights, so far the program is going very well. The main window of the application represents a physical light board, similar to what you might see in the sound booth at concerts. I'm using WPF for the project. Wpf has given me many issues, although my program is gorgeous in aesthetics, it lacks in smoothness due to WPF's way of doing things.

Ok so to the point, I have usercontrols representing faders and knobs, I want to update these knobs and faders to reflect what is happening, so in turn, sync everything up. Is there an alternative to using the dispatcher to send commands to update the GUI? Am I using the dispatcher wrong? This is what my code looks like withing a control that is an inheritance of usercontrol when a change to the control needs to be made.

VB
Private Sub Change(sender As Object, ByVal e As DMXProcessor.ChangeArgs)
        If channels.Count = 1 Then
            For Each z As Integer In channels
                If z = e.channel Then Slider1.Dispatcher.BeginInvoke(New MDelegate(AddressOf ChangeDispacter), e.channel, e.value)
            Next
        End If
    End Sub


What would solve everything is if I could directly implement my changes within the draw of the control, so every time the control is drawn by the graphics, the control checks to see if it needs to be changed, and if so, updates itself accordingly, all on the same thread, no dispatcher nonsense.

NOTE: I've noticed too many dispatcher calls called too close to each other hangs my program, this is why I want a different approach, like I said, someone tell me if I'm not dispatching right. ALSO I don't mind replies in C#, I use C# as often as I use VB.
Posted
Updated 24-Mar-13 19:13pm
v2

1 solution


It sounds likely that the ChangeDispacter is doing too much work for the UI thread.



If so, then one approach is to break the ChangeDispacter task down into smaller UI operations as shown in the code below. This should work as it appears that the MDelegate has no return value or it is not significant. And that is the approach the code is currently attempting to use.


However, if you are using .NET 4.5, then a far better solution, is to transform the ChangeDispacter method into an Async version and call it concurrently. That is shown in the second code block.



Using the current approach:


C#
private void Change(object sender, ChangeArgs e)
{
    if (channels.Count == 1)
    {
        foreach (int z in channels)
        {
            if (z == e.channel)
            {
                ChangeDispacterThreaded(e.channel, e.value);
            }
        }
    }
}

public void ChangeDispacterThreaded(int channel, object value)
{
    Slider1.Dispatcher.BeginInvoke(new MDelegate(ChangeDispacterUI_1)
        , new object[] { channel, value });

    // do some threaded non UI things

    Slider1.Dispatcher.BeginInvoke(new MDelegate(ChangeDispacterUI_2)
        , new object[] { channel, value });
}

public void ChangeDispacterUI_1(int channel, object value)
{
    // do UI things
}

public void ChangeDispacterUI_2(int channel, object value)
{
    // do UI things
}



.NET 4.5 Using the asynch-concurrent approach


C#
private async Task Change(object sender, ChangeArgs e)
{
    if (channels.Count == 1)
    {
        foreach (int z in channels)
        {
            if (z == e.channel)
            {
                await ChangeDispacterThreaded(e.channel, e.value);
            }
        }
    }
}

public async Task ChangeDispacterThreaded(int channel, object value)
{
    await Slider1.Dispatcher.BeginInvoke(
        new Action<int,object>((a,b) => ChangeDispacterUI_1(a,b))
        , new object[] { channel, value });

    // do some threaded non UI things

    await  Slider1.Dispatcher.BeginInvoke(
        new Action<int, object>((a, b) => ChangeDispacterUI_1(a, b))
        , new object[] { channel, value });
}

public void ChangeDispacterUI_1(int channel, object value)
{
    // do UI things
}

public void ChangeDispacterUI_2(int channel, object value)
{
    // do UI things
}
 
Share this answer
 
Comments
jakethesnake12543 25-Mar-13 23:16pm    
Solution worked, I did some tidying up in my code as well to have less code in the method the dispatcher sends, thus, less for the UI thread to process. The code within the ChangeDispacter method checked to see if the user had his mouse over the control, apparently that check alone took a (long) while for the system to validate.
CognitiveFeedback 12-Jun-13 0:43am    
I missed your reply until now ... it's good to know that your code is working well
good luck with it

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