Wpf datagrid don't refresh dynamic - wpf

I have the following code, where TabResultadoBusqueda is a Datagrid.
My problem is when I click in one button of this window , it's frozen until the operation finishes.
I would like that the user could be doing other things while Datagrid is loading, as the time to perform the operation is 1 min,.
Example code event Click in one Button:
TabResultadoBusqueda.ItemsSource = null;
TabResultadoBusqueda.ItemsSource = (IEnumerable<articuloPOCO>)cambioDeArticuloListaAArticuloPOCOlista(m.todosArticulosPAGINADOS(0, 50));
TabResultadoBusqueda.Dispatcher.BeginInvoke(DispatcherPriority.Background,
new Action(
() => aaaa1()
)
);
code of aaaa1:
for (int j = 2; j < 15; j++)
{
((List<articuloPOCO>)TabResultadoBusqueda.ItemsSource).AddRange((IEnumerable<articuloPOCO>)cambioDeArticuloListaAArticuloPOCOlista(m.todosArticulosPAGINADOS(j, 50)));
TabResultadoBusqueda.Items.Refresh();
}
Any help will be good.

Do your long running operation on a separate thread. This will keep your UI thread unblocked and responsive. It looks like a BackgroundWorker will be good for your situation. Read about it here http://msdn.microsoft.com/en-us/library/system.componentmodel.backgroundworker.aspx

Related

UI Thread stuck for about 4 seconds and dispatcher.BeginInvoke() doesn't solve it

In my ListBox, I have over 50 thousands airports listed. When a particular airport is selected, I need to load its runway and other information on the UI. Here is my code:
private void ListAirport_SelectedIndexChanged(object sender, SelectionChangedEventArgs e)
{
...
Dispatcher.BeginInvoke(new Action(() =>
{
DataTable dt = TxtFileToTable(Environment.CurrentDirectory + #"\\r5_IOS.txt");
for (int i = 0; i < dt.Rows.Count; i++)
{
if (ListAirport.SelectedItem != null && ListAirport.SelectedItem.ToString() == dt.Rows[i][0].ToString())
{
ListRunway.Items.Add(dt.Rows[i][1]);
ListRunway.SelectedIndex = 0;//select the default runway
}
}
}
));
}
I want to use Dispatcher.BeginInvoke to avoid the UI getting stuck but it doesn't seem to help. Why and How can I avoid the UI getting stuck? Thanks.
You definitely shouldn't show 50k items in ListBox. Think about some smarter solution.
Dispatcher.BeginInvoke makes your action run on UI-thread. But your handler ListAirport_SelectedIndexChanged is already on UI-thread, so you don't have to BeginInvoke. Instead of it you should do your hard work in another thread, and show result in UI-thread.

Why does focusing a TextBox speed up another thread's progress?

Hello Stackoverflowers!
I have a strange situation here. I wrote a small C# tool, to measure the time it takes to send a request via usb and wait until the response arrives. The communication is no problem, nor are the devices.
I put a simple TextBox on the GUI together with a "Start" button.
Pressing "Start" starts a thread with a loop (loops defined in the TextBox) sending requests and receiving the answers. In the GUI thread you can see a progress bar showing the status.
When I pressed "Start" I measured around 15 ms per command and response (in average) which is quite a long time.
When I pressed "Start" and clicked inside the TextBox (only setting the cursor inside), the worker thread ran through with an average time of 1.6 ms per command and response.
This is reproducible in my case. I even put in a new, totally useless TextBox. When clicking inside, the thread speeds up, when I focus another element, like a slider, the thread slows down again.
Has anyone ever heard about something like that and can explain to me, why this happens? And even better, how I can avoid this behavior?
FYI:
- I tried both BackgroundWorker and Thread, same behavior.
- For taking the times, I'm using .NET's stopwatch.
- Executing the measurement method in the GUI thread changes nothing. EDIT: Tried again and everything's as it should be. But now I have the problem, that the GUI freezes, since I'm working in its thread.
- Removing the progress bar changes nothing.
Thanks a lot!
EDIT:
private void tbAmount_Copy_PreviewKeyUp(object sender, KeyEventArgs e)
{
if (e.Key == Key.Enter)
{
if (String.IsNullOrEmpty(tbDevAddrTime.Text))
return;
pbTimeMeasure.Value = 0;
worker = new BackgroundWorker();
worker.DoWork += new DoWorkEventHandler(StartTimeMeasureHandler);
worker.RunWorkerAsync();
}
}
private void StartTimeMeasure()
{
int address = 1;
int loops = 1;
DispatchIfNecessary(() =>
{
address = Convert.ToInt32(tbDevAddrTime.Text);
loops = Convert.ToInt32(tbAmount_Copy.Text);
pbTimeMeasure.Maximum = loops;
});
System.Diagnostics.Stopwatch stopwatchLong = new System.Diagnostics.Stopwatch();
System.Diagnostics.Stopwatch stopwatchShort = new System.Diagnostics.Stopwatch();
var cmd = String.Format(":{0:X3}4010200300000000\r", RequestAddress + address);
for (int i = 0; i < loops; i++)
{
stopwatchLong.Start();
//SND
_canbus.Write(cmd, cmd.Length, ref _bytesWritten);
stopwatchShort.Start();
Thread.Sleep(1);
//RCV
var answer = ReadContent();
stopwatchShort.Stop();
stopwatchLong.Stop();
DispatchIfNecessary(() =>
{
pbTimeMeasure.Value++;
});
}
Double resLong = Convert.ToDouble(stopwatchLong.ElapsedMilliseconds);
Double resLongAvg = resLong / loops;
Double resShort = Convert.ToDouble(stopwatchShort.ElapsedMilliseconds);
Double resShortAvg = resShort / loops;
DispatchIfNecessary(() =>
{
lbTotalResLong.Content = resLong.ToString();
lbTotalResShort.Content = resShort.ToString();
int length = 5;
if (resLongAvg.ToString().Length < 5)
{
length = resLong.ToString().Length;
}
if (resShortAvg.ToString().Length < length)
{
length = resShortAvg.ToString().Length;
}
lbAvgResLong.Content = resLongAvg.ToString().Substring(0,length);
lbAvgResShort.Content = resShortAvg.ToString().Substring(0,length);
});
}

Modal Progress Dialog - How to pass in delegate?

I have a basic form with a progress bar and want to pass in a delegate of sorts like this:
ProgressDialog.ShowAndExecute(delegate);
I can't figure out how to connect the delegate to progress messages.
void ShowAndExecute()
{
// Handle form disabling and whatnot...
thread = new Thread(new ThreadStart(ExecuteCommand));
while (thread.IsAlive)
{
Application.DoEvents();
Thread.Sleep(100);
}
}
// Example of the method I would like to pass in
void ExecuteCommand()
{
for (int i = 0; i < 10; i++) Thread.Sleep(1000);
}
I thought about creating an interface that the commands should implement. They can fire an event whenever an update occurs, but how do I let the calling thread know it was fired?
How do you handle passing in delegates that report progress through events and act (move progress bar) based on those? This is a static dialog (to make it easier to call throughout the app)
Only the ExecuteCommand knows its current progress. So some interface or class must be passed to the ExecuteCommand method. The ExecuteCommand will set the progress, then it's up to the implementation of the listener to determine what to do with the progress. In general, the listener will check if it's a significant change** in progress, and if so, it will BeginInvoke a call to update a progress bar.
** - If you process thousands of items in a short period of time, then you want to protect against calling BeginInvoke too much, otherwise it will lock up the UI thread.
void ExecuteCommand(IThreadController tc)
{
for (int i = 0; i < 10; i++) {
Thread.Sleep(1000);
tc.setProgress("processing ...", (i+1), 10);
}
}

Remove button from memory which is removed from Grid

In my application, i am generating multiple buttons at run time and add it to grid as following
for (int i = 0; i < ListOfMainCategories.Count; i++)
{
clsMainCategory tempCat = (clsMainCategory)ListOfMainCategories[i];
ButtonMainMenuCat btn = CreateMainButton(tempCat.CatTitle, i);
btn.Margin = new Thickness(0, 1, 0, 1);
btn.TabIndex = TabIndexNo;
if (i == 0)
{
buttonHomeMenu = btn;
}
btn.AddHandler(ButtonMainMenuSubSubCat.GotKeyboardFocusEvent, new RoutedEventHandler(ButtonMainMenuGotFocus), handledEventsToo: false);
// stackTableViewMainMenu.Children.Add(btn);
Grid.SetRow(btn, 1);
Grid.SetColumn(btn, i + 1);
gridHeader.Children.Add(btn);
}
After on particular event I removed all of these buttons from Grid.
gridHeader.Children.RemoveRange(0, gridHeader.Children.Count);
Here i Think i also need to Remove or dispose or unload these button from Memory. So How can i do this task ? Please suggest
Yuo can't dispose of the button in the classical sense as there is nothing to dispose. You are dealing with managed code here. The memory allocation will be cleared up by the garbage collector as long as there are no references. In the code above you are keeping a reference to the button through the routed event handler so call btn.RemoveHandler before you remove it from the Grid.
You could take a look at MSDN guidance on the WeakEvent pattern here: http://msdn.microsoft.com/en-us/library/aa970850

While pausing a Storyboard, Does the Property being animated get locked ? Does the AnimationClock stops?

ParallelTimeline OTimelineAnimation = new ParallelTimeline();
for (int i = 0; i < _Bubbles.Count; i++)
{
_StryBrd.Children.Clear();
PointAnimation ToMovePointAnim = new PointAnimation();
ToMovePointAnim.From = _Bubbles[i].CurrentPoint;
ToMovePointAnim.To = _Bubbles[i].ToNextPoint;
ToMovePointAnim.Duration = new Duration(TimeSpan.FromSeconds(1.5));
ToMovePointAnim.FillBehavior = FillBehavior.Stop;
Storyboard.SetTarget(ToMovePointAnim, _Bubbles[i].CurrentElement);
Storyboard.SetTargetProperty(ToMovePointAnim, new PropertyPath(ScatterViewItem.CenterProperty));
OTimelineAnimation.Children.Add(ToMovePointAnim);
_Bubbles[i].CurrentElement.Center = _Bubbles[i].ToNextPoint;
_Bubbles[i].CurrentPoint = _Bubbles[i].ToNextPoint;
_Bubbles[i].ToNextPoint = GetToNextPoint(_Bubbles[i].ToNextPoint);
}
_StryBrd.Children.Add(OTimelineAnimation);
_StryBrd.Begin(this, true);
// At another part X, I call the following
_StryBrd.Pause(this);
// At another part Y, I call the following
_StryBrd.Resume(this);
Problem:
While I try to drag any of these "ScatterViewItem" elements which internally ( I guess ! ) it is accessing the "ScatterViewItem.CenterProperty" somehow to change the position of the elements, its not being dragged.
Is this the default behaviour for pausing a storyboard ? ( To lock the property from being changed )
I hope I had clarified enough, Thank all in advance
Well, animations have quite extreme precedence, you cannot modify animated properties, even when paused. Just setting a property after an animation is trouble enough, here you also would need to get rid of the animation to change it.

Resources