I have created an Excel Add-In in Visual Studio 2008 for Excel 2003 that (among other things) clears object data from multiple excel sheets based on user selection. The add-in runs as it should, however, at random intervals on various actions will cause Excel to crash. The code below contains a windows form with a progress bar, background worker and open file dialog (ofd). This exception gets thrown: Microsoft.VisualStudio.Debugger.Runtime.Main.ThrowCrossThreadMessageException (in case it isn't obvious) during the Main() event at this.progressbar1.Text. I have tried several different methods to resolve this problem and it may be reflected in this code snippet - perhaps someone could enlighten me as to what I am doing wrong and what - if any of the methods that have been added - may be unnecessary.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Excel = Microsoft.Office.Interop.Excel;
using System.Runtime.InteropServices;
using System.Threading;
using Microsoft.Win32;
namespace WindowsFormApplication
{
public partial class Form3 : Form
{
private int highestPercentageReached = 0;
private bool skipreadonly = true;
public Form3()
{
InitializeComponent();
}
private void Form3_Load(object sender, EventArgs e)
{
Thread newThread = new Thread(new ThreadStart(main));
newThread.SetApartmentState(ApartmentState.STA);
newThread.Start();
}
[STAThread]
private void main()
{
if ((bool)Invoke(new ExcelSelectHandler(ExcelSelect)))
{
Invoke(new MethodInvoker(this.Show));
backgroundWorker1.RunWorkerAsync();
}
else
{
Invoke(new MethodInvoker(this.Close));
}
}
private void Form3_KeyPress(object sender, KeyPressEventArgs e)
{
if (e.KeyChar == (Char)Keys.Escape)
{
backgroundWorker1.CancelAsync();
}
}
private delegate bool ExcelSelectHandler();
private bool ExcelSelect()
{
Invoke(new MethodInvoker(this.Hide));
ofd.Title = "Excel Reset";
ofd.Multiselect = true;
ofd.FileName = "";
ofd.Filter = "Excel Files|*.xls;*.xlsx;*.xlt;*.xltx;*.xlsb;*.xlsm;*.xltm";
DialogResult result = ofd.ShowDialog();
return result == DialogResult.OK;
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = sender as BackgroundWorker;
DataRemove(worker, e);
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
MethodInvoker proginvoke = delegate
{
progressBar1.Value = e.ProgressPercentage;
};
progressBar1.BeginInvoke(proginvoke);
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Error != null)
{
MessageBox.Show(e.Error.Message);
}
else if (e.Cancelled)
{
Invoke(new MethodInvoker(this.Close));
}
else
{
Invoke(new MethodInvoker(this.Close));
}
}
private void DataRemove(BackgroundWorker worker, DoWorkEventArgs e)
{
try
{
object missing = System.Reflection.Missing.Value;
int k = ofd.FileNames.Length;
int l = 0;
Excel.Application eapp = ThisAddIn.xlApplication;
Excel.Workbook eawb = eapp.ActiveWorkbook;
Excel.Application xlApp = new Microsoft.Office.Interop.Excel.Application();
xlApp.ScreenUpdating = false;
xlApp.Visible = false;
Excel.Workbook xlWorkbook;
foreach (var filename in ofd.FileNames)
{
if (l < k)
{
if (filename != eawb.FullName)
{
xlWorkbook = xlApp.Workbooks.Open(ofd.FileNames[l].ToString(), missing, missing, missing, missing, missing, true, missing, missing, missing, true, missing, missing, missing, missing);
Excel.Worksheet xlWorksheet = (Excel.Worksheet)xlApp.ActiveSheet;
Excel.ListRows xlRows = (Excel.ListRows)xlWorksheet.ListObjects;
if (xlWorkbook.ReadOnly)
{
if (skipreadonly)
{
xlWorkbook.Close(false, missing, missing);
}
else
{
Invoke(new MethodInvoker(this.Hide));
if (MessageBox.Show("Excel document '" + ofd.SafeFileNames[l].ToString() + "' is either opened or marked read only and data will not removed from this file. Do you want to ignore this file and continue removing data?", "Data Remover", MessageBoxButtons.YesNo) == DialogResult.No)
{
Invoke(new MethodInvoker(this.Show));
if (worker.WorkerSupportsCancellation == true)
{
worker.CancelAsync();
xlWorkbook.Close(false, missing, missing);
break;
}
}
else
{
Invoke(new MethodInvoker(this.Show));
xlWorkbook.Close(false, missing, missing);
}
}
}
else
{
if (xlRows.Count > 0)
{
foreach (Excel.ListRow xlRow in xlRows)
{
xlRow.Delete();
}
}
xlWorkbook.Save();
xlWorkbook.Close(true, missing, missing);
}
Marshal.ReleaseComObject(xlRows);
Marshal.ReleaseComObject(xlWorksheet);
Marshal.ReleaseComObject(xlWorkbook);
}
else
{
Excel.Worksheet exlWorksheet = (Excel.Worksheet)eawb.ActiveSheet;
Excel.ListRows xlRows = (Excel.ListRows)exlWorksheet.ListObjects;
foreach (Excel.ListRow xlRow in xlRows)
{
xlRow.Delete();
}
}
l += 1;
}
if (worker.CancellationPending)
{
e.Cancel = true;
break;
}
else
{
int percentComplete = l / k * 100;
highestPercentageReached = percentComplete;
worker.ReportProgress(percentComplete);
}
}
xlApp.Quit();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
Marshal.FinalReleaseComObject(xlApp);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
Related
The following is my Calculator program.How can i write a NUnit test case for add
functionality?
I want create a separate project for as CalculatorTest and there i want access Form1 by creating an object for Form1.
Here i am unable to create an object for Form1 in CalculatorTest.
Note:I have added references of nunit and my calculator namespace.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Threading;
namespace Calculater
{
public partial class Form1 : Form
{
double value;
string operator_clicked;
bool isResult = false;
public Form1()
{
InitializeComponent();
txtresult.Text = "0";
}
private void btn1_Click(object sender, EventArgs e)
{
if (txtresult.Text == "0" || isResult)
{
txtresult.Clear();
isResult = false;
}
Button btn = (Button)sender;
txtresult.Text = txtresult.Text + btn.Text;
}
private void btnclr_Click(object sender, EventArgs e)
{
txtresult.Text="0";
value = 0;
}
private void btnequal_Click(object sender, EventArgs e)
{
if(value>=0 && txtresult.Text!=string.Empty)
{
switch(operator_clicked)
{
case "+":
txtresult.Text = (value + double.Parse(txtresult.Text)).ToString();
break;
case "-":
txtresult.Text = (value - double.Parse(txtresult.Text)).ToString();
break;
case "X":
txtresult.Text = (value * double.Parse(txtresult.Text)).ToString();
break;
case "/":
try
{
txtresult.Text = (value / double.Parse(txtresult.Text)).ToString();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message);
txtresult.Clear();
}
break;
}
txttop.Clear();
isResult = true;
}
}
private void btnOperator_Click(object sender, EventArgs e)
{
if(txtresult.Text!=string.Empty)
{
Button btnOperator = (Button)sender;
txttop.Text = txtresult.Text + btnOperator.Text;
operator_clicked = btnOperator.Text;
value = double.Parse(txtresult.Text);
txtresult.Clear();
}
else
{
MessageBox.Show("Please enter any number");
}
}
}
}
I have a WPF combobox like this :
<ComboBox x:Name="CustomerComboBox" IsEditable="True" ItemsSource="{Binding Relations.View}"
DisplayMemberPath="Model.sname" />
If I click in the editable combo while the binding is in place (MVVM) to give it focus, and I then press and hold any key, I assume the combo will be filled with that key rather quickly, but it isn't.
If I remove the displaymemberpath and then do the same, then I have the expected behavior. Of course I really need the binding.
The performance penalty only shows when the combo has a lot of elements mine has 6000.
I cannot understand where this performance penalty is coming from. Is there any way to bypass this problem ?
Below code solves the issues by creating a specialised combobox that basically caches all binding results. I created it by looking at the orginal source code of the combobox and itemscontrol using .NET reflector.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Reflection;
using System.ComponentModel;
using System.Collections.ObjectModel;
using System.Windows.Controls.Primitives;
using System.Collections;
namespace ICeTechControlLibrary
{
public class FastEditComboBox : ComboBox
{
//PARTS
private TextBox _TextBoxPart = null;
//DEPENDENCY PROPERTIES
public static readonly DependencyProperty TextProperty
= DependencyProperty.Register("Text", typeof(string), typeof(AutoCompleteTextBox), new FrameworkPropertyMetadata(string.Empty, FrameworkPropertyMetadataOptions.Journal | FrameworkPropertyMetadataOptions.BindsTwoWayByDefault, new PropertyChangedCallback(FastEditComboBox.OnTextChanged)));
private List<string> _CompletionStrings = new List<string>();
private int _textBoxSelectionStart;
private bool _updatingText;
private bool _updatingSelectedItem;
private static Dictionary<TextBox, FastEditComboBox> _TextBoxDictionary = new Dictionary<TextBox,FastEditComboBox>();
static FastEditComboBox()
{
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.TextChangedEvent, new TextChangedEventHandler(FastEditComboBox.OnTextChanged));
EventManager.RegisterClassHandler(typeof(TextBox), TextBox.SelectionChangedEvent, new RoutedEventHandler(FastEditComboBox.OnSelectionChanged));
}
public string Text
{
get
{
return (string)base.GetValue(TextProperty);
}
set
{
base.SetValue(TextProperty, value);
}
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_TextBoxPart = base.GetTemplateChild("PART_EditableTextBox") as TextBox;
if (!_TextBoxDictionary.ContainsKey(_TextBoxPart)) _TextBoxDictionary.Add(_TextBoxPart, this);
}
private void OnTextBoxSelectionChanged(object sender, RoutedEventArgs e)
{
this._textBoxSelectionStart = this._TextBoxPart.SelectionStart;
}
private void OnTextBoxTextChanged(object sender, TextChangedEventArgs e)
{
if (IsEditable)
{
TextUpdated(_TextBoxPart.Text, true);
}
}
private void TextUpdated(string newText, bool textBoxUpdated)
{
if (!_updatingText && !_updatingSelectedItem)
{
try
{
_updatingText = true;
if (base.IsTextSearchEnabled)
{
int num = FindMatchingPrefix(newText);
if (num >= 0)
{
if (textBoxUpdated)
{
int selectionStart = this._TextBoxPart.SelectionStart;
if ((selectionStart == newText.Length) && (selectionStart > this._textBoxSelectionStart))
{
string primaryTextFromItem = _CompletionStrings[num];
this._TextBoxPart.Text = primaryTextFromItem;
this._TextBoxPart.SelectionStart = newText.Length;
this._TextBoxPart.SelectionLength = primaryTextFromItem.Length - newText.Length;
newText = primaryTextFromItem;
}
}
else
{
string b = _CompletionStrings[num];
if (!string.Equals(newText, b, StringComparison.CurrentCulture))
{
num = -1;
}
}
}
if (num != base.SelectedIndex)
{
SelectedIndex = num;
}
}
if (textBoxUpdated)
{
Text = newText;
}
else if (_TextBoxPart != null)
{
_TextBoxPart.Text = newText;
}
}
finally
{
_updatingText = false;
}
}
}
internal void SelectedItemUpdated()
{
try
{
this._updatingSelectedItem = true;
if (!this._updatingText)
{
string primaryTextFromItem = GetPrimaryTextFromItem(SelectedItem);
Text = primaryTextFromItem;
}
this.Update();
}
finally
{
this._updatingSelectedItem = false;
}
}
private void Update()
{
if (this.IsEditable)
{
this.UpdateEditableTextBox();
}
else
{
//this.UpdateSelectionBoxItem();
}
}
private void UpdateEditableTextBox()
{
if (!_updatingText)
{
try
{
this._updatingText = true;
string text = this.Text;
if ((this._TextBoxPart != null) && (this._TextBoxPart.Text != text))
{
this._TextBoxPart.Text = text;
this._TextBoxPart.SelectAll();
}
}
finally
{
this._updatingText = false;
}
}
}
protected override void OnSelectionChanged(SelectionChangedEventArgs e)
{
base.RaiseEvent(e);
this.SelectedItemUpdated();
if (this.IsDropDownOpen)
{
object Item = SelectedItem;
if (Item != null)
{
base.OnSelectionChanged(e);
}
//object internalSelectedItem = base.InternalSelectedItem;
//if (internalSelectedItem != null)
//{
// base.NavigateToItem(internalSelectedItem, ItemsControl.ItemNavigateArgs.Empty);
//}
}
}
int FindMatchingPrefix(string s)
{
int index = _CompletionStrings.BinarySearch(s, StringComparer.OrdinalIgnoreCase);
if (index >= 0) return index;
index = ~index;
string p = _CompletionStrings[index];
if (p.StartsWith(s, StringComparison.CurrentCultureIgnoreCase)) return index;
return -1;
}
protected override void OnDisplayMemberPathChanged(string oldDisplayMemberPath, string newDisplayMemberPath)
{
FillCompletionStrings();
}
protected override void OnItemsChanged(System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
{
base.OnItemsChanged(e);
switch (e.Action)
{
case System.Collections.Specialized.NotifyCollectionChangedAction.Add:
AddCompletionStrings(e.NewItems);
break;
case System.Collections.Specialized.NotifyCollectionChangedAction.Remove:
RemoveCompletionStrings(e.OldItems);
break;
case System.Collections.Specialized.NotifyCollectionChangedAction.Reset:
FillCompletionStrings();
break;
}
}
private void FillCompletionStrings()
{
_CompletionStrings.Clear();
AddCompletionStrings(Items);
}
private void RemoveCompletionStrings(IList items)
{
foreach (object o in items)
{
RemoveCompletionStringForItem(o);
}
}
private void AddCompletionStrings(IList items)
{
foreach (object o in items)
{
AddCompletionStringForItem(o);
}
}
private void AddCompletionStringForItem(object item)
{
Binding binding = new Binding(DisplayMemberPath);
TextBlock tb = new TextBlock();
tb.DataContext = item;
tb.SetBinding(TextBlock.TextProperty, binding);
string s = tb.Text;
int index = _CompletionStrings.BinarySearch(s, StringComparer.OrdinalIgnoreCase);
if (index < 0)
{
_CompletionStrings.Insert(~index, s);
}
else
{
_CompletionStrings.Insert(index, s);
}
}
private string GetPrimaryTextFromItem(object item)
{
Binding binding = new Binding(DisplayMemberPath);
TextBlock tb = new TextBlock();
tb.DataContext = item;
tb.SetBinding(TextBlock.TextProperty, binding);
string s = tb.Text;
return s;
}
private void RemoveCompletionStringForItem(object item)
{
Binding binding = new Binding(DisplayMemberPath);
TextBlock tb = new TextBlock();
tb.DataContext = item;
tb.SetBinding(TextBlock.TextProperty, binding);
string s = tb.Text;
int index = _CompletionStrings.BinarySearch(s, StringComparer.OrdinalIgnoreCase);
if (index >= 0) _CompletionStrings.RemoveAt(index);
}
private static void OnTextChanged(object sender, TextChangedEventArgs e)
{
TextBox tb = e.Source as TextBox;
if (tb.Name == "PART_EditableTextBox")
{
if (_TextBoxDictionary.ContainsKey(tb))
{
FastEditComboBox combo = _TextBoxDictionary[tb];
combo.OnTextBoxTextChanged(sender, e);
e.Handled = true;
}
}
}
private static void OnSelectionChanged(object sender, RoutedEventArgs e)
{
TextBox tb = e.Source as TextBox;
if (tb.Name == "PART_EditableTextBox")
{
if (_TextBoxDictionary.ContainsKey(tb))
{
FastEditComboBox combo = _TextBoxDictionary[tb];
combo.OnTextBoxSelectionChanged(sender, e);
e.Handled = true;
}
}
}
private static void OnTextChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
FastEditComboBox actb = (FastEditComboBox)d;
actb.TextUpdated((string)e.NewValue, false);
}
}
}
selecting the very first element clears the selection with this implementation.
so still some bugs here
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 have a WinForms application that is calling a business class method that performs some heavy duty action taking about 5 seconds for each call. The main form calls this method in a loop. This loop can run from 10 times to maybe up to 10 thousand times.
The WinForms application sends a parameter to the business class and has an area to display the time taken for each method call and what the value returned by the method. How do I inform my main window and update a text area in the main winform with what the method has returned for each call?
Currently the data comes all at once after all the threads have finished. Is there a way to update the UI for all the iterations of the loop once the each call is done? I don't mind if it is done sequentially also.
The FORM
HeavyDutyClass hd;
public Form1()
{
InitializeComponent();
hd = new HeavyDutyClass();
}
//BUTTON CLICK
private void Start_Click(object sender, EventArgs e)
{
int filecount = 5000; //BAD - opening 5000 threads! Any other approach?
hd.FileProcessed += new EventHandler(hd_FileProcessed);
var threads = new Thread[filecount];
for (int i = 0; i < filecount; i++)
{
threads[i] = new Thread(() => { hd.LongRunningMethod(); });
threads[i].Start();
}
}
//BUSINESS CLASS EVENT THAT FIRES WHEN BUSINESS METHOD COMPELTES
void hd_FileProcessed(object sender, EventArgs e)
{
if (dgv.InvokeRequired)
{
dgv.Invoke((MethodInvoker)delegate { UpdateGrid(); });
}
}
private void UpdateGrid()
{
dgv.Rows.Add(1);
int i = dgv.Rows.Count;
dgv.Rows [ i-1].Selected = true;
dgv.FirstDisplayedScrollingRowIndex = i - 1;
}
The business HeavyDuty class
public event EventHandler FileProcessed;
public HeavyDutyClass()
{
}
protected virtual void OnMyEvent(EventArgs e)
{
if (FileProcessed != null)
{
FileProcessed(this, e);
}
}
public bool LongRunningMethod()
{
for (double i = 0; i < 199990000; i++)
{
//time consuming loop
}
OnMyEvent(EventArgs.Empty);
return true;
}
Add a Winforms Project, Drop a Label Control on the Form , Copy-Paste this code and Hit F5
[EDIT]: Updated with the business class comment from the user
NB: My form class is named Form3. You may have to change your Program.cs or vice-versa.
using System.ComponentModel;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public class BusinessClass
{
public int MyFunction(int input)
{
return input+10;
}
}
public partial class Form3 : Form
{
private BackgroundWorker _worker;
BusinessClass _biz = new BusinessClass();
public Form3()
{
InitializeComponent();
InitWorker();
}
private void InitWorker()
{
if (_worker != null)
{
_worker.Dispose();
}
_worker = new BackgroundWorker
{
WorkerReportsProgress = true,
WorkerSupportsCancellation = true
};
_worker.DoWork += DoWork;
_worker.RunWorkerCompleted += RunWorkerCompleted;
_worker.ProgressChanged += ProgressChanged;
_worker.RunWorkerAsync();
}
void DoWork(object sender, DoWorkEventArgs e)
{
int highestPercentageReached = 0;
if (_worker.CancellationPending)
{
e.Cancel = true;
}
else
{
double i = 0.0d;
int junk = 0;
for (i = 0; i <= 199990000; i++)
{
int result = _biz.MyFunction(junk);
junk++;
// Report progress as a percentage of the total task.
var percentComplete = (int)(i / 199990000 * 100);
if (percentComplete > highestPercentageReached)
{
highestPercentageReached = percentComplete;
// note I can pass the business class result also and display the same in the LABEL
_worker.ReportProgress(percentComplete, result);
_worker.CancelAsync();
}
}
}
}
void RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
{
// Display some message to the user that task has been
// cancelled
}
else if (e.Error != null)
{
// Do something with the error
}
}
void ProgressChanged(object sender, ProgressChangedEventArgs e)
{
label1.Text = string.Format("Result {0}: Percent {1}",e.UserState, e.ProgressPercentage);
}
}
}
With this you can achieve Cancel functionality also very easily.
Observe that during initialisation, I set the WorkerSupportsCancellation = true & then I check for _worker.CancellationPending in the DoWork. So, if you want to cancel the process by a Cancel Button click, then you will write this code in the button handler- _worker.CancelAsync();
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