I have an issue with ProcessChanged. It's fired in the code (when I'm looking in the debugger) but it doesn't update in my mainscreen where the progressbar is located.
The initialisation of the BackgroundWorker
private void Import_Click(object sender, RoutedEventArgs e)
{
progressbarImport.Value = 0;
int max = DatagridZegrisWeekImport.Items.Count;
BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += worker_DoWork;
worker.ProgressChanged += worker_ProgressChanged;
worker.WorkerReportsProgress = true;
worker.RunWorkerCompleted += worker_RunWorkerCompleted;
worker.RunWorkerAsync();
}
The DoWork
void worker_DoWork(object sender, DoWorkEventArgs e)
{
var manager = new ZegrisReadToDB();
int progressPercentage = 0;
int max = DatagridZegrisWeekImport.Items.Count;
for (int i = 0; i < max; i++)
{
this.Dispatcher.Invoke(() =>
{
DatagridZegrisWeekImport.SelectedIndex = i;
var selecteditem = DatagridZegrisWeekImport.SelectedItem as ZegrisWeekDataImport;
string exist = manager.CheckExist2(selecteditem.Artikelnummer, selecteditem.Jaar);
if (exist == "")
{
insert statement;
progressPercentage = Convert.ToInt32(((double)i / max) * 100);
(sender as BackgroundWorker).ReportProgress(progressPercentage);
Thread.Sleep(100);
}
else
{
update statement
progressPercentage = Convert.ToInt32(((double)i / max) * 100);
(sender as BackgroundWorker).ReportProgress(progressPercentage);
Thread.Sleep(100);
}
});
}
}
The ProgressChanged
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
Application.Current.Dispatcher.Invoke(() =>
this.progressbarImport.Value = e.ProgressPercentage);
}
As you may see, I have already tried a couple of solutions found on this forum, but none seem te be working.
It's the first time I'm using BackgroundWorker and somewhere I lost my train of thought.
If you are intent on using the BackgroundWorker then try the following code
void worker_DoWork(object sender, DoWorkEventArgs e)
{
var manager = new ZegrisReadToDB();
int progressPercentage = 0;
// use the source list if you have it available, rather than casting here
List<ZegrisWeekDataImport> items = DatagridZegrisWeekImport.Items.Cast<ZegrisWeekDataImport>().ToList();
var max = items.Count;
for (int i = 0; i < max; i++)
{
var item = items[i];
string exist = manager.CheckExist2(item.Artikelnummer, item.Jaar);
if (exist == "")
{
insert statement;
progressPercentage = Convert.ToInt32(((double)i / max) * 100);
(sender as BackgroundWorker).ReportProgress(progressPercentage);
}
else
{
update statement
progressPercentage = Convert.ToInt32(((double)i / max) * 100);
(sender as BackgroundWorker).ReportProgress(progressPercentage);
}
}
}
void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.progressbarImport.Value = e.ProgressPercentage);
}
If you have control of your ZegrisReadToDB class it would be beneficial to make this async if you can. Below is a version that uses async/await
// bind you progress bar to this
public double Progress { get; set; } // raise property changed
// bind your datagrid to this property
public List<ZegrisWeekDataImport> Items {get;set;} = new List<ZegrisWeekDataImport>();
private async void Import_Click(object sender, RoutedEventArgs e)
{
await DoWork();
}
public async Task DoWork()
{
for (int i = 0; i < Items.Count; i++)
{
var item = Items[i];
string exist = await manager.CheckExist2(item.Artikelnummer, item.Jaar);
if (exist == "")
{
await insert statement
}
else
{
await update statement
}
Progress = (double)i / max) * 100;
}
}
Related
I have some troubles while making simple application on C# / Windows.Forms that simulates a pendulum.
It's a simple application with all backend logic in form code.
First of all, I set up the interval equals 100 milliseconds (line 60), but when I calculate number of turns (line 155) and display it, displaying message:
refresh every second (not every 100 milliseconds)
and it behaves like this: 1-2-4-5-6-8 or 1-3-4-5-7-8 etc.
I don't know when it started bugging and want to determine the mistake.
Thanks a lot for your help.
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Koban_Lab1
{
public partial class mainWindow : Form
{
public Point pendFulcrum = new Point(150, 0);
public Point pendTip = new Point();
private bool deviceState_;
private long ticks_;
private DateTime startTiming;
private Pen blackPencil;
public static double g = 9.8;
public double T;
public double periodInTicks;
public double L;
public double a;
public double Amp;
public double startOffset;
public double w;
public double periodCounter;
public double x;
public double y;
public double currentAngle;
private Timer timer_;
public double t;
public Bitmap field;
private long cnt = 0;
private bool DeviceState
{
get
{
return deviceState_;
}
set
{
if (value == deviceState_)
{
return;
}
deviceState_ = value;
switch (value)
{
case true:
L = Convert.ToDouble(pendulumLengthTextBox.Text) / 100;
a = Convert.ToDouble(plummetDistanceTextBox.Text) / 100;
periodCounter = 0;
T = 2 * Math.PI * Math.Sqrt((L * L) / (12 * g * a) + a / g);
w = 2 * Math.PI / T;
Amp = 2 * Math.PI * L / 24;
startOffset = Amp;
startTiming = DateTime.Now;
timer_ = new Timer();
timer_.Interval = 100;
timer_.Tick += new EventHandler(tickTimer);
timer_.Start();
startPendulumButton.Enabled = false;
stopPendulumButton.Enabled = true;
pendulumLengthTextBox.Enabled = false;
plummetDistanceTextBox.Enabled = false;
addReadoutButton.Enabled = true;
break;
case false:
timer_.Stop();
timer_ = null;
startPendulumButton.Enabled = true;
stopPendulumButton.Enabled = false;
pendulumLengthTextBox.Enabled = true;
plummetDistanceTextBox.Enabled = true;
timerTextBox1.Text = Locale.timerDisabledMessage;
timerTextBox2.Text = "0";
addReadoutButton.Enabled = false;
break;
}
return;
}
}
public Graphics fieldGraphics;
public mainWindow()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
pendulumLengthTooltip.SetToolTip(pendulumLengthTextBox, Locale.pendulumLengthTooltipMessage);
plummetDistanceTooltip.SetToolTip(plummetDistanceTextBox, Locale.plummetDistanceTooltipMessage);
blackPencil = Pens.Gray;
timerTextBox1.Text = Locale.timerDisabledMessage;
timerTextBox2.Text = "0";
deleteReadoutButton.Enabled = false;
DeviceState = false;
field = new Bitmap(pendulumField.Width, pendulumField.Height);
}
private void startPendulumButton_Click(object sender, EventArgs e)
{
DeviceState = true;
}
private void stopPendulumButton_Click(object sender, EventArgs e)
{
DeviceState = false;
}
private void addReadoutButton_Click(object sender, EventArgs e)
{
if (timerTextBox1.Text == Locale.timerDisabledMessage)
{
return;
}
readoutList.Items.Add(timerTextBox1.Text);
deleteReadoutButton.Enabled = true;
return;
}
private void deleteReadoutButton_Click(object sender, EventArgs e)
{
if (readoutList.SelectedIndex != (-1))
{
readoutList.Items.RemoveAt(readoutList.SelectedIndex);
}
else
{
readoutList.Items.RemoveAt(readoutList.Items.Count - 1);
}
if (readoutList.Items.Count == 0)
{
deleteReadoutButton.Enabled = false;
}
}
private void tickTimer(object sender, EventArgs e)
{
ticks_ = DateTime.Now.Ticks - startTiming.Ticks;
timerTextBox1.Text = TimeSpan.FromTicks(ticks_).ToString(#"mm\:ss\:ff");
timerTextBox2.Text = periodCounter.ToString();
ticks_ = DateTime.Now.Ticks - startTiming.Ticks;
t = ticks_ / TimeSpan.TicksPerSecond;
periodCounter = t / T;
timerTextBox2.Text = Convert.ToInt32(periodCounter).ToString();
currentAngle = Amp * Math.Sin(w * t);
x = x * Math.Cos(currentAngle) - y * Math.Sin(currentAngle);
y = x * Math.Sin(currentAngle) + y * Math.Cos(currentAngle);
Program.labWindow.fieldGraphics = Graphics.FromHwnd(Program.labWindow.pendulumField.Handle);
pendTip.X = (int)x;
pendTip.Y = (int)y;
fieldGraphics.DrawLine(blackPencil, pendFulcrum, pendTip);
pendulumField.Image = field;
Application.DoEvents();
}
private void plummetDistanceTooltip_Popup(object sender, PopupEventArgs e)
{
}
private void plummetDistanceLabel_Click(object sender, EventArgs e)
{
}
}
}
In wpf application - UI getting freezed on button click - then how to show busy indicator while huge data processing?
I have tried background worker process, but its throwing the below exception.
The "calling thread" in the message is not your UI thread...
Sample Code:
private void bw_DoWork(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle);
BackgroundWorker worker = sender as BackgroundWorker;
this.busyIndicator.Visibility = Visibility.Visible;
busyIndicator.IsBusy = true;
for (int k = 1; (k <= 10); k++)
{
if ((worker.CancellationPending == true))
{
e.Cancel = true;
break;
}
else
{
int intAutomationID = 0;
int intAutomation_SS_ID = 0;
int intAS_ID = 0;
string strProcedureName = "";
//busyIndicator.Visibility = Visibility.Visible;
try
{
// Insert entry into AUTOMATION_PROCESS table.
intAutomationID = Pkg_TargetsIdentifiers.InsertAutomationProcess(Convert.ToInt32(cmbIdentifier.SelectedValue),
Convert.ToInt32(cmbSourceData.SelectedValue), "InProgress", 0, "Insert");
if (intAutomationID > 0)
{
for (int i = 0; i <= dgvProcessLists.Items.Count - 1; i++)
{
int j = 3;
strProcedureName = "";
strProcedureName = (dgvProcessLists.Items[i] as DataRowView).Row.ItemArray[j].ToString();
if (!string.IsNullOrEmpty(strProcedureName))
{
//AS_ID
// InitializeMouseHandlersForVisual(dgvProcessLists);
intAS_ID = Convert.ToInt32((dgvProcessLists.Items[i] as DataRowView).Row.ItemArray[0].ToString());
intAutomation_SS_ID = Pkg_TargetsIdentifiers.InsertAutomationStepsStatus(intAS_ID, intAutomationID,
"Inprogress", 0, "Insert");
bool boolStatus = Pkg_TargetsIdentifiers.CallActionProcess(strProcedureName, intAutomationID);
if (boolStatus == true)
{
//var selectedRow = DataProcessing.Class1.GetSelectedRow(this.dgvProcessLists);
//var columnCell = DataProcessing.Class1.GetRow(this.dgvProcessLists,0);
intAutomation_SS_ID = Pkg_TargetsIdentifiers.InsertAutomationStepsStatus(intAS_ID, intAutomationID,
"Completed", intAutomation_SS_ID, "Update");
intAS_ID = 0;
strProcedureName = "";
DataRowView row = (dgvProcessLists.Items[i] as DataRowView);
if (row != null)
{
if (row.DataView.Table.Columns.Contains("Status"))
{
Type type = row["Status"].GetType();
string status = row["Status"] == System.DBNull.Value ? null : (string)row["Status"];
if (boolStatus == true)
{
Uri uri = new Uri("pack://application:,,,/Images/green.jpg");
BitmapImage source = new BitmapImage(uri);
}
if (boolStatus == false)
{
Uri uri = new Uri("pack://application:,,,/Images/red.jpg");
BitmapImage source = new BitmapImage(uri);
}
}
}
continue;
}
else
{
break;
}
}
}
intAutomationID = Pkg_TargetsIdentifiers.InsertAutomationProcess(Convert.ToInt32(cmbIdentifier.SelectedValue),
Convert.ToInt32(cmbSourceData.SelectedValue), "Completed", intAutomationID, "Update");
}
// Perform a time consuming operation and report progress.
System.Threading.Thread.Sleep(500);
worker.ReportProgress((k * 10));
}
catch (Exception ex)
{
throw ex;
}
finally
{ }
}
}
}
private void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Dispatcher.Invoke(new Action(() => { }), DispatcherPriority.ContextIdle);
if ((e.Cancelled == true))
{
this.busyIndicator.Visibility = Visibility.Hidden;
busyIndicator.IsBusy = false;
}
else if (!(e.Error == null))
{
this.busyIndicator.Visibility = Visibility.Hidden;
busyIndicator.IsBusy = false;
}
else
{
this.busyIndicator.Visibility = Visibility.Hidden;
busyIndicator.IsBusy = false;
}
}
private void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
this.busyIndicator.Visibility = Visibility.Visible;
busyIndicator.IsBusy = true;
}
/// <summary>
/// btnStartProcess_Click
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnStartProcess_Click(object sender, RoutedEventArgs e)
{
try
{
if (bw.IsBusy != true)
{
bw.RunWorkerAsync();
}
//worker.RunWorkerAsync();
// //};
// //worker.RunWorkerCompleted += (o, ea) =>
// //{
// // busyIndicator.Visibility = Visibility.Hidden;
// // busyIndicator.IsBusy = false;
// //};
// //worker.RunWorkerAsync();
// //};
// //worker.RunWorkerAsync();
//bw.RunWorkerCompleted += (o, ea) =>
//{
// busyIndicator.IsBusy = false;
// busyIndicator.Visibility = Visibility.Hidden;
//};
//busyIndicator.IsBusy = true;
//busyIndicator.Visibility = Visibility.Visible;
//bw.RunWorkerAsync();
}
catch (Exception ex)
{
throw ex;
}
}
Please do the needful..
Thanks and Regards,
Vijay Babu
First, you need to get your BackgroundWorker code working. For this, I'd advise you to see my answer to the How to correctly implement a BackgroundWorker with ProgressBar updates? question, which provides a clear, concise code example.
I'm now assuming that you have correctly set up your BackgroundWorker, so we can move onto displaying a busy indicator. First, you need to be aware of the reason for your error:
We cannot call any functions on any UI objects from any other thread than the UI thread
Bearing this in mind, that means that we can't set the Visiblity of any busy indicator from a background thread. So, the easiest fix is to set it to Visibility.Visible before starting the BackgroundWorker:
busyIndicator.Visibility = Visibility.Visible;
busyIndicator.IsBusy = true;
backgroundWorker.RunWorkerAsync();
As we can see from the ooo page on MSDN:
You must be careful not to manipulate any user-interface objects in your DoWork event handler. Instead, communicate to the user interface through the ProgressChanged and RunWorkerCompleted events.
This basically means that we can handle these events on the UI thread and so we have access to our UI elements from these event handlers. Therefore, when your long running process is complete, the RunWorkerCompleted event will be called. If you handle this event, then you can hide your busy indicator in the relevant event handler:
private void BackgroundWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
busyIndicator.Visibility = Visibility.Hidden;
busyIndicator.IsBusy = false;
}
As it runs on the UI thread, there is no need to call Dispatcher.Invoke, and it's worth noting that your call to this method does nothing because you didn't provide any delegate method for it to run:
Dispatcher.Invoke(new Action(() => { /*No action*/ }), DispatcherPriority.ContextIdle);
Try this:
Dispatcher.Invoke(() => { busyIndicator.Visibility = Visibility.Visible; });
{
System.Threading.ThreadStart start = delegate()
{
CallAutomationProcess();
//done doing work, send result to the UI thread
Dispatcher.Invoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(changest));
};
this.busyIndicator.IsBusy = true;
this.busyIndicator.Visibility = Visibility.Visible;
new System.Threading.Thread(start).Start();
I have a kinect project in wpf and it uses skeleton stream that tracks the left and right hand of its users and allows me to hover over buttons.
I tried making a new form and just copying and pasting everything so i can create a new page but it didnt work, i think i may have to reference the methods used in the main page, but i am unsure.
I want to be able to use the skeleton stream alongside the hovering method in a new window
Any help would be appreciated - i apologize if this does not make sense i am a beginner
Code
public partial class MainWindow : Window
{
private KinectSensor _Kinect;
private WriteableBitmap _ColorImageBitmap;
private Int32Rect _ColorImageBitmapRect;
private int _ColorImageStride;
private Skeleton[] FrameSkeletons;
List<Button> buttons;
static Button selected;
float handX;
float handY;
public MainWindow()
{
InitializeComponent();
InitializeButtons();
kinectButton.Click += new RoutedEventHandler(kinectButton_Click);
this.Loaded += (s, e) => { DiscoverKinectSensor(); };
this.Unloaded += (s, e) => { this.Kinect = null; };
}
//initialize buttons to be checked
private void InitializeButtons()
{
buttons = new List<Button> { button1, button2, quitButton};
}
//raise event for Kinect sensor status changed
private void DiscoverKinectSensor()
{
KinectSensor.KinectSensors.StatusChanged += KinectSensors_StatusChanged;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
}
private void KinectSensors_StatusChanged(object sender, StatusChangedEventArgs e)
{
switch (e.Status)
{
case KinectStatus.Connected:
if (this.Kinect == null)
{
this.Kinect = e.Sensor;
}
break;
case KinectStatus.Disconnected:
if (this.Kinect == e.Sensor)
{
this.Kinect = null;
this.Kinect = KinectSensor.KinectSensors.FirstOrDefault(x => x.Status == KinectStatus.Connected);
if (this.Kinect == null)
{
MessageBox.Show("Sensor Disconnected. Please reconnect to continue.");
}
}
break;
}
}
public KinectSensor Kinect
{
get { return this._Kinect; }
set
{
if (this._Kinect != value)
{
if (this._Kinect != null)
{
UninitializeKinectSensor(this._Kinect);
this._Kinect = null;
}
if (value != null && value.Status == KinectStatus.Connected)
{
this._Kinect = value;
InitializeKinectSensor(this._Kinect);
}
}
}
}
private void UninitializeKinectSensor(KinectSensor kinectSensor)
{
if (kinectSensor != null)
{
kinectSensor.Stop();
kinectSensor.ColorFrameReady -= Kinect_ColorFrameReady;
kinectSensor.SkeletonFrameReady -= Kinect_SkeletonFrameReady;
}
}
private void InitializeKinectSensor(KinectSensor kinectSensor)
{
if (kinectSensor != null)
{
ColorImageStream colorStream = kinectSensor.ColorStream;
colorStream.Enable();
this._ColorImageBitmap = new WriteableBitmap(colorStream.FrameWidth, colorStream.FrameHeight,
96, 96, PixelFormats.Bgr32, null);
this._ColorImageBitmapRect = new Int32Rect(0, 0, colorStream.FrameWidth, colorStream.FrameHeight);
this._ColorImageStride = colorStream.FrameWidth * colorStream.FrameBytesPerPixel;
videoStream.Source = this._ColorImageBitmap;
kinectSensor.SkeletonStream.Enable(new TransformSmoothParameters()
{
Correction = 0.5f,
JitterRadius = 0.05f,
MaxDeviationRadius = 0.04f,
Smoothing = 0.5f
});
kinectSensor.SkeletonFrameReady += Kinect_SkeletonFrameReady;
kinectSensor.ColorFrameReady += Kinect_ColorFrameReady;
kinectSensor.Start();
this.FrameSkeletons = new Skeleton[this.Kinect.SkeletonStream.FrameSkeletonArrayLength];
}
}
private void Kinect_ColorFrameReady(object sender, ColorImageFrameReadyEventArgs e)
{
using (ColorImageFrame frame = e.OpenColorImageFrame())
{
if (frame != null)
{
byte[] pixelData = new byte[frame.PixelDataLength];
frame.CopyPixelDataTo(pixelData);
this._ColorImageBitmap.WritePixels(this._ColorImageBitmapRect, pixelData,
this._ColorImageStride, 0);
}
}
}
private void Kinect_SkeletonFrameReady(object sender, SkeletonFrameReadyEventArgs e)
{
using (SkeletonFrame frame = e.OpenSkeletonFrame())
{
if (frame != null)
{
frame.CopySkeletonDataTo(this.FrameSkeletons);
Skeleton skeleton = GetPrimarySkeleton(this.FrameSkeletons);
if (skeleton == null)
{
kinectButton.Visibility = Visibility.Collapsed;
}
else
{
Joint primaryHand = GetPrimaryHand(skeleton);
TrackHand(primaryHand);
}
}
}
}
//track and display hand
private void TrackHand(Joint hand)
{
if (hand.TrackingState == JointTrackingState.NotTracked)
{
kinectButton.Visibility = System.Windows.Visibility.Collapsed;
}
else
{
kinectButton.Visibility = System.Windows.Visibility.Visible;
DepthImagePoint point = this.Kinect.MapSkeletonPointToDepth(hand.Position, DepthImageFormat.Resolution640x480Fps30);
handX = (int)((point.X * LayoutRoot.ActualWidth / this.Kinect.DepthStream.FrameWidth) -
(kinectButton.ActualWidth / 2.0));
handY = (int)((point.Y * LayoutRoot.ActualHeight / this.Kinect.DepthStream.FrameHeight) -
(kinectButton.ActualHeight / 2.0));
Canvas.SetLeft(kinectButton, handX);
Canvas.SetTop(kinectButton, handY);
if (isHandOver(kinectButton, buttons)) kinectButton.Hovering();
else kinectButton.Release();
if (hand.JointType == JointType.HandRight)
{
kinectButton.ImageSource = "/Images/RightHand.png";
kinectButton.ActiveImageSource = "/Images/RightHand.png";
}
else
{
kinectButton.ImageSource = "/Images/LeftHand.png";
kinectButton.ActiveImageSource = "/Images/LeftHand.png";
}
}
}
//detect if hand is overlapping over any button
private bool isHandOver(FrameworkElement hand, List<Button> buttonslist)
{
var handTopLeft = new Point(Canvas.GetLeft(hand), Canvas.GetTop(hand));
var handX = handTopLeft.X + hand.ActualWidth / 2;
var handY = handTopLeft.Y + hand.ActualHeight / 2;
foreach (Button target in buttonslist)
{
Point targetTopLeft = new Point(Canvas.GetLeft(target), Canvas.GetTop(target));
if (handX > targetTopLeft.X &&
handX < targetTopLeft.X + target.Width &&
handY > targetTopLeft.Y &&
handY < targetTopLeft.Y + target.Height)
{
selected = target;
return true;
}
}
return false;
}
//get the hand closest to the Kinect sensor
private static Joint GetPrimaryHand(Skeleton skeleton)
{
Joint primaryHand = new Joint();
if (skeleton != null)
{
primaryHand = skeleton.Joints[JointType.HandLeft];
Joint rightHand = skeleton.Joints[JointType.HandRight];
if (rightHand.TrackingState != JointTrackingState.NotTracked)
{
if (primaryHand.TrackingState == JointTrackingState.NotTracked)
{
primaryHand = rightHand;
}
else
{
if (primaryHand.Position.Z > rightHand.Position.Z)
{
primaryHand = rightHand;
}
}
}
}
return primaryHand;
}
//get the skeleton closest to the Kinect sensor
private static Skeleton GetPrimarySkeleton(Skeleton[] skeletons)
{
Skeleton skeleton = null;
if (skeletons != null)
{
for (int i = 0; i < skeletons.Length; i++)
{
if (skeletons[i].TrackingState == SkeletonTrackingState.Tracked)
{
if (skeleton == null)
{
skeleton = skeletons[i];
}
else
{
if (skeleton.Position.Z > skeletons[i].Position.Z)
{
skeleton = skeletons[i];
}
}
}
}
}
return skeleton;
}
void kinectButton_Click(object sender, RoutedEventArgs e)
{
selected.RaiseEvent(new RoutedEventArgs(Button.ClickEvent, selected));
}
private void button1_Click(object sender, RoutedEventArgs e)
{
message.Content = "Button 1 clicked!";
}
private void button2_Click(object sender, RoutedEventArgs e)
{
message.Content = "Button 2 clicked!";
}
private void quitButton_Click(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
}
}
You can do this in a couple of different ways, and more ways then what is below.
You could pass a reference to the sensor itself to the new window when it is created:
public MainWindow()
{
// init code for window and Kinect
// show the second window
SecondWindow mySecondWindow = new SecondWindow(_Kinect);
mySecondWindow.Show();
// other stuff...
}
public class SecondWindow : Window
{
public SecondWindow(KinectSensor sensor)
{
// ... stuff
sensor.SkeletonFrameReady += SkeletonFrameReadyCallback;
// ... more stuff
}
}
Then subscribe to the SkeletonFrameReady callback in your second window. This might work for your situation if you are interacting with items in the seconds window.
Another way would be to create a public callback inside your second window and subscribe it to the SkeletonFrameReady event.
public MainWindow()
{
// init code for window and Kinect
// show the second window
SecondWindow mySecondWindow = new SecondWindow(_Kinect);
mySecondWindow.Show();
_Kinect.SkeletonFrameReady += mySecondWindow.SkeletonFrameReadyCallback;
}
I also notice in your code that you are firing events. If you are wanting to act on events from one window in a different window, you can subscribe to those custom events in the same mentioned above.
I want to simulate a drag/drop event in WPF.
For this I'll need to gain access to the data stored in the "Drag/Drop buffer" and also I'll need to create a DragEventArgs.
I noticed that the DragEventArgs is sealed and has no public ctor.
So my questions are:
1. how can I create an instance of DragEventArgs?
2. How can I gain access to the drag/drop buffer?
i recently do this! i simulated drag/drop with MouseDown, MouseMove and MouseUp events. for example for my application, i have some canvases that i want to drag and drop them. every canvas has an id. in MouseDown event, i buffer its id and use it in MouseMove and MouseUp event. Desktop_Canvas is my main Canvas that contains some canvases. these canvases are in my dictionary (dic).
here is my code:
private Dictionary<int, Win> dic = new Dictionary<int, Win>();
private Point downPoint_Drag = new Point(-1, -1);
private int id_Drag = -1;
private bool flag_Drag = false;
public class Win
{
public Canvas canvas = new Canvas();
public Point downpoint = new Point();
public Win()
{
canvas.Background = new SolidColorBrush(Colors.Gray);
}
}
private void Desktop_Canvas_MouseMove(object sender, MouseEventArgs e)
{
try
{
Point movePoint = e.GetPosition(Desktop_Canvas);
if (flag_Drag && downPoint_Drag != new Point(-1, -1))
{
double dy1 = movePoint.Y - downPoint_Drag.Y, x = -1, dx1 = movePoint.X - downPoint_Drag.X, y = -1;
downPoint_Drag = movePoint;
if (x == -1)
x = Canvas.GetLeft(dic[id_Drag].canvas) + dx1;
if (y == -1)
y = Canvas.GetTop(dic[id_Drag].canvas) + dy1;
Canvas.SetLeft(dic[id_Drag].canvas, x);
Canvas.SetTop(dic[id_Drag].canvas, y);
}
}
catch
{
MouseEventArgs ee = new MouseEventArgs((MouseDevice)e.Device, 10);
Desktop_Canvas_MouseLeave(null, ee);
}
}
private void Desktop_Canvas_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
try
{
downPoint_Drag = new Point(-1, -1);
id_Drag =-1;
flag_Drag = false;
}
catch
{
MouseEventArgs ee = new MouseEventArgs((MouseDevice)e.Device, 10);
Desktop_Canvas_MouseLeave(null, ee);
}
}
private void Desktop_Canvas_MouseLeave(object sender, MouseEventArgs e)
{
MouseButtonEventArgs ee = new MouseButtonEventArgs((MouseDevice)e.Device, 10, MouseButton.Left);
Desktop_Canvas_MouseLeftButtonUp(null, ee);
}
void canvas_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
downPoint_Drag = e.GetPosition(Desktop_Canvas);
int hoverId = HoverWin(downPoint_Drag);
flag_Drag = true;
id_Drag = hoverId;
dic[id_Drag].downpoint = new Point(downPoint_Drag.X, downPoint_Drag.Y);
}
private int HoverWin(Point p)
{
foreach (int i in dic.Keys)
{
if (dic[i].canvas.IsMouseOver)
return i;
}
return -1;
}
I've written a WPF application that uses many Frame controls to view camera feeds. When deployed, it crashes pretty randomly (anywhere from 2 hours to 16+ hours), and I see these in the event log, consecutively:
System.AccessViolationException:
Attempted to read or write protected
memory. This is often an indication
that other memory is corrupt. at
MS.Win32.UnsafeNativeMethods.DispatchMessage(MSG&
msg) at
System.Windows.Threading.Dispatcher.PushFrameImpl(DispatcherFrame
frame) at
System.Windows.Threading.Dispatcher.PushFrame(DispatcherFrame
frame) at
System.Windows.Threading.Dispatcher.Run()
at
System.Windows.Application.RunDispatcher(Object
ignore) at
System.Windows.Application.RunInternal(Window
window) at
System.Windows.Application.Run(Window
window) at
System.Windows.Application.Run() at
Status_Station_client.MainClass.Main()
Faulting application status station
client.exe, version 1.0.0.0, stamp
4ad0faa5, faulting module msvfw32.dll,
version 5.1.2600.2180, stamp 41109753,
debug? 0, fault address 0x00002642.
Any ideas on how to track this down? The web pages do contain ActiveX controls, so a first guess is there's a problem there.
I haven't been able to trace this in Debug mode. Another thing I have thought of trying is swallowing the exception from the navigation call, but am unsure if this is a wise thing to do:
try
{
if (Frame1 != null)
Frame1.Source = new Uri(uriWithResolution);
}
catch (AccessViolationException ex)
{
// log message
}
EDIT: Here's some more source code, I'm stumped as to where the error is (i.e. where the exception is being thrown)
MatrixView.cs:
public partial class MatrixView : Window
{
System.Timers.Timer timer;
int pageNumber = 0;
IEnumerable<List<CameraInfo>> _cameraList;
GlobalSettings _globalSettings;
Screen _screen;
public MatrixView(List<CameraInfo> cameras, int pageFlipInterval, int camerasPerPage, GlobalSettings globalSettings, Screen screen)
{
InitializeComponent();
_globalSettings = globalSettings;
_screen = screen;
_cameraList = Partition<CameraInfo>(cameras, camerasPerPage);
this.Dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(Dispatcher_UnhandledException);
displayCameras();
timer = new System.Timers.Timer(pageFlipInterval * 1000); // interval (in seconds) * 1000 ms / s
timer.Elapsed += new ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
this.KeyUp += new System.Windows.Input.KeyEventHandler(MatrixView_KeyUp);
if (globalSettings.FullScreenOnLoad)
{
this.WindowStyle = WindowStyle.None;
}
}
void MatrixView_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (this.WindowStyle == WindowStyle.None)
{
if (e.Key == Key.F11 || e.Key == Key.Escape)
{
this.WindowStyle = WindowStyle.SingleBorderWindow;
}
}
else
{
if (e.Key == Key.F11)
{
this.WindowStyle = WindowStyle.None;
}
}
this.WindowState = WindowState.Maximized;
}
void timer_Elapsed(object sender, ElapsedEventArgs e)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new ThreadStart(delegate()
{
displayCameras();
}));
}
void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
EventLog.WriteEntry("Matrix Monitor", string.Format("Unhandled exception from Matrix Dispatcher\r\nMessage: {0}\r\nSource: {1}\r\nInnerException: {2}\r\nStack Trace: {3}\r\nFull String: {4}", e.Exception.Message, e.Exception.Source, e.Exception.InnerException, e.Exception.StackTrace, e.Exception.ToString()));
e.Handled = true;
}
private void displayCameras()
{
foreach (var child in uniformGrid1.Children)
{
FrameTimer c = child as FrameTimer;
if (c != null)
{
c.Dispose();
c = null;
}
}
GC.Collect();
GC.WaitForPendingFinalizers();
uniformGrid1.Children.Clear();
List<CameraInfo> camerasInPage = _cameraList.ElementAt(pageNumber);
int numCameras = camerasInPage.Count;
int sqrtOfCameras = (int) Math.Sqrt(numCameras);
double height = _screen.Bounds.Height / sqrtOfCameras;
double width = _screen.Bounds.Width / sqrtOfCameras;
foreach (CameraInfo camera in camerasInPage)
{
uniformGrid1.Children.Add(new FrameTimer(camera, _globalSettings, height, width));
}
pageNumber++;
if (pageNumber >= _cameraList.Count<List<CameraInfo>>())
{
pageNumber = 0;
}
}
public static IEnumerable<List<T>> Partition<T>(IList<T> source, int size)
{
int remainder = source.Count % size == 0 ? 0 : 1;
for (int i = 0; i < (source.Count / size) + remainder; i++)
yield return new List<T>(source.Skip(size * i).Take(size));
}
}
FrameTimer.cs:
public partial class FrameTimer : UserControl, IDisposable
{
System.Timers.Timer timer;
string _uri;
string _noImageUrl;
bool? _successState = null;
GlobalSettings _globalSettings;
CameraInfo _camera;
Ping ping;
double _height;
double _width;
public FrameTimer(CameraInfo camera, GlobalSettings globalSettings, double height, double width)
{
InitializeComponent();
_noImageUrl = AppDomain.CurrentDomain.BaseDirectory + "noImage.jpg";
_globalSettings = globalSettings;
_camera = camera;
_height = height;
_width = width;
_uri = string.Format("http://{0}:{1}/LiveView.aspx?camera={2}", globalSettings.ServerIPAddress, globalSettings.ServerPort, camera.camName);
this.Dispatcher.UnhandledException += new DispatcherUnhandledExceptionEventHandler(Dispatcher_UnhandledException);
setUrl();
timer = new System.Timers.Timer(_globalSettings.PingInterval * 1000);
timer.Elapsed += new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = true;
}
void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
EventLog.WriteEntry("Matrix Monitor", string.Format("Unhandled exception from Frame Dispatcher\r\nMessage: {0}\r\nSource: {1}\r\nInnerException: {2}\r\nStack Trace: {3}\r\nFull String: {4}", e.Exception.Message, e.Exception.Source, e.Exception.InnerException, e.Exception.StackTrace, e.Exception.ToString()));
e.Handled = true;
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
this.Dispatcher.BeginInvoke(DispatcherPriority.Send, new ThreadStart(delegate()
{
setUrl();
}));
}
private void setUrl()
{
ping = new Ping();
ping.PingCompleted += new PingCompletedEventHandler(ping_PingCompleted);
videoChecks checks = new videoChecks();
string ipAddressToUse = checks.isIPInternal(_camera.camIP) ? _camera.camIP : _camera.camExtIP;
ping.SendAsync(ipAddressToUse, 1000, null);
}
void ping_PingCompleted(object sender, PingCompletedEventArgs e)
{
try
{
if (e.Reply.Status == IPStatus.Success)
{
if (_successState == null || _successState == false)
{
_successState = true;
string uriWithResolution = string.Format("{0}&res={1}x{2}&header=0", _uri, (int)_width, (int)_height);
if (Frame1 != null)
Frame1.Source = new Uri(uriWithResolution);
}
}
else
{
if (_successState == null || _successState == true)
{
_successState = false;
Image1.Source = new BitmapImage(new Uri(_noImageUrl));
}
}
}
catch (ObjectDisposedException ex)
{
Dispose();
}
finally
{
((IDisposable)sender).Dispose();
}
}
#region IDisposable Members
public void Dispose()
{
if (timer != null)
{
timer.Elapsed -= new System.Timers.ElapsedEventHandler(timer_Elapsed);
timer.Enabled = false;
timer.Dispose();
timer = null;
}
Frame1.Source = null;
if (ping != null)
{
ping.PingCompleted -= new PingCompletedEventHandler(ping_PingCompleted);
((IDisposable)ping).Dispose();
ping = null;
}
}
#endregion
}
If you look at the faulting module at the bottom your stacktrace, you will see msvfw32.dll. This is not a DLL used by WPF, so I assume it's coming from some active-x within a web page you are loading. I'm even more convinced of that due to your code implying something dealing with cameras/video and msvfw32 deals with video (its very old too!!). It's showing up in the Dispatcher loop because the Dispatcher also handles a Win32 message loop, that is ultimately used by the alleged activex.
Also, try checking for the exception here, maybe you can set the argument Handled=true