I have a routine which is called upon a background worker completing. As below;
private void BatteryListFetchBackgroundWorkerRunWorkerCompleter(object sender, RunWorkerCompletedEventArgs e)
{
this.Cursor = Cursors.Default;
var sortedList = this.currentBatteries.Values.OrderBy(g => g, new BatteryNameComparer()); //breaks here
this.BatteryBindingSource.DataSource = sortedList;
if (this.batteryListBox.Items.Count > 0)
{
this.batteryListBox.SetSelected(0, true);
}
this.viewScheduleButton.Enabled = true;
this.viewDefaultScheduleButton.Enabled = true;
this.viewEditScheduleLimits.Enabled = true;
}
The line it's breaking at is;
this.BatteryBindingSource.DataSource = sortedList;
The exception is null reference exception and it occurs when setting the data source
The code for BatteryNameComparer
public class BatteryNameComparer : IComparer<Battery>
{
/// <summary>
/// Compares DDSMGroup
/// </summary>
/// <param name="a">first value for comparison</param>
/// <param name="b">second value for comparison</param>
/// <returns>An integer indicating the compare result</returns>
public int Compare(Battery a, Battery b)
{
int aId = int.Parse(a.DeviceName.Substring(BatteryOverviewControl.BatteryPrefixSubstring.Length));
int bId = int.Parse(b.DeviceName.Substring(BatteryOverviewControl.BatteryPrefixSubstring.Length));
return aId.CompareTo(bId);
}
}
Whenever you see a TargetInvocationException, you should immediately inspect its InnerException property to find the exception that was actually thrown.
http://msdn.microsoft.com/en-us/library/system.exception.innerexception(v=vs.110).aspx
Simply put, a TargetInvocationException tells you only that another exception was thrown within some sort of invocation context - this is nearly always a cross thread operation or call via reflection.
how to avoid the error of FileSystemWatcher in C#?
too many changes at once in directory
I have to detect all changes on a network share.
The InternalBufferSize is increased to 8192 * 128
There are two things you should do:
Set InternalBufferSize to the maximum supported value (65536). Your attempt to set it to "8192 * 128" is larger than the maximum supported value listed in the documentation, so you may not have increased the buffer size at all.
Queue events from the FileSystemWatcher onto a background thread for processing.
It's the second point here that isn't well understood, and really should be documented on MSDN. Internally, FileSystemWatcher is queuing change events into that internal buffer you set the size of above. Critically however, items are only removed from that buffer after your event handler returns. This means every cycle of overhead your event handlers introduce increases the possibility of the buffer filling up. What you should do is clear the limited queue of the FileSystemWatcher as quickly as possible, and move the events into your own infinite queue, to process at the rate you can handle, or discard if you care to do so, but with some intelligence around it.
Here's basically what I do in my code. First, I start my own dispatcher thread:
Dispatcher changeDispatcher = null;
ManualResetEvent changeDispatcherStarted = new ManualResetEvent(false);
Action changeThreadHandler = () =>
{
changeDispatcher = Dispatcher.CurrentDispatcher;
changeDispatcherStarted.Set();
Dispatcher.Run();
};
new Thread(() => changeThreadHandler()) { IsBackground = true }.Start();
changeDispatcherStarted.WaitOne();
Then I create the watcher. Note the buffer size being set. In my case, I only watch changes in the target directory, not subdirectories:
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = path;
watcher.InternalBufferSize = 64 * 1024;
watcher.IncludeSubdirectories = false;
Now I attach my event handlers, but here I invoke them onto my dispatcher rather than running them synchronously in the watcher thread. Yes, the events will be processed in order by the dispatcher:
watcher.Changed += (sender, e) => changeDispatcher.BeginInvoke(new Action(() => OnChanged(sender, e)));
watcher.Created += (sender, e) => changeDispatcher.BeginInvoke(new Action(() => OnCreated(sender, e)));
watcher.Deleted += (sender, e) => changeDispatcher.BeginInvoke(new Action(() => OnDeleted(sender, e)));
watcher.Renamed += (sender, e) => changeDispatcher.BeginInvoke(new Action(() => OnRenamed(sender, e)));
And finally, after disposing of the FileSystemWatcher (you were doing that, right?), you need to shut down your dispatcher:
watcher.Dispose()
changeDispatcher.BeginInvokeShutdown(DispatcherPriority.Normal);
And that's it. I was getting this problem myself, both in network and local scenarios. After using this approach, I wasn't able to generate this error again, even when hammering out empty files to watched directories as fast as possible. If you did ever manage to somehow exhaust the buffer in this case (which I'm not sure is possible, the API upstream is probably slower), there's still further room for optimization here. As long as your dispatcher is over the "tipping point" though, where the sender can't post the events faster than you can dispatch them, you'll never get a backlog, and hence never blow the buffer. I believe this approach puts you into that safe area.
I think I might have found a pattern that can help improve the the usage of the buffer considerably.
The issue with this class is that until the delegates for the events finish running, it cannot release the memory it uses to hold that information.
For the life of me I don't know why the maximum InternalBufferSize was set to 64Kb, but with this idea you'll use that small buffer much more effectively.
If instead of doing the operations inside the delegates you simply queue them and defer their execution for a background worker, the amount of memory used by it will be considerably smaller.
In fact, I've got no idea why the class in itself doesn't implement something like this in the first place.
The code below is just a sample piece of code for the idea, and shouldn't be used in production environments, but it increased the number of files I could copy and keep track of drastically.
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.IO;
using System.Threading;
using NUnit.Framework;
namespace Soundnet.Synchronisation.FileSystemWatcherTests
{
/// <summary>
///
/// </summary>
[TestFixture]
public class Tests
{
static readonly ConcurrentQueue<Change> ChangesQueue = new ConcurrentQueue<Change>();
const string Destination = #"c:\Destination";
const string Source = #"c:\Source";
/// <summary>
/// Tests this instance.
/// </summary>
[Test]
public void Test()
{
var changesBackgroundWorker = new BackgroundWorker();
changesBackgroundWorker.DoWork += ChangesBackgroundWorkerOnDoWork;
changesBackgroundWorker.RunWorkerAsync();
var fileSystemWatcher = new FileSystemWatcher
{
Path = Source,
EnableRaisingEvents = true,
IncludeSubdirectories = true,
NotifyFilter = NotifyFilters.LastWrite | NotifyFilters.LastAccess | NotifyFilters.CreationTime | NotifyFilters.FileName | NotifyFilters.DirectoryName,
InternalBufferSize = 65536
};
fileSystemWatcher.Created += FileSystemWatcherOnCreated;
fileSystemWatcher.Deleted += FileSystemWatcherOnDeleted;
fileSystemWatcher.Renamed += FileSystemWatcherOnRenamed;
fileSystemWatcher.Error += FileSystemWatcherOnError;
while (true)
Thread.Sleep(1000000);
}
/// <summary>
/// Changeses the background worker configuration document work.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="doWorkEventArgs">The <see cref="DoWorkEventArgs"/> instance containing the event data.</param>
/// <exception cref="System.ArgumentOutOfRangeException"></exception>
private static void ChangesBackgroundWorkerOnDoWork(object sender, DoWorkEventArgs doWorkEventArgs)
{
while (true)
{
Change change;
if (ChangesQueue.TryDequeue(out change))
{
var backgroundWorker = new BackgroundWorker();
switch (change.ChangeType)
{
case WatcherChangeTypes.Created:
backgroundWorker.DoWork += (o, args) =>
{
var fileSystemType = GetFileSystemType(change.FullPath);
var newItem = Path.Combine(Destination, change.Name);
while (true)
{
try
{
switch (fileSystemType)
{
case FileSystemType.File:
File.Copy(change.FullPath, newItem, true);
break;
case FileSystemType.Directory:
var directorySecurity =
Directory.GetAccessControl(change.FullPath);
Directory.CreateDirectory(newItem, directorySecurity);
break;
case FileSystemType.NotExistant:
break;
}
return;
}
catch (IOException exception)
{
Thread.Sleep(100);
Console.WriteLine(exception.Message);
}
}
};
break;
case WatcherChangeTypes.Deleted:
backgroundWorker.DoWork += (o, args) =>
{
var itemToDelete = Path.Combine(Destination, change.Name);
var fileSystemType = GetFileSystemType(itemToDelete);
switch (fileSystemType)
{
case FileSystemType.File:
File.Delete(itemToDelete);
break;
case FileSystemType.Directory:
Directory.Delete(itemToDelete, true);
break;
}
};
break;
case WatcherChangeTypes.Changed:
backgroundWorker.DoWork += (o, args) =>
{
var fileSystemType = GetFileSystemType(change.FullPath);
var newItem = Path.Combine(Destination, change.Name);
switch (fileSystemType)
{
case FileSystemType.File:
File.Copy(change.FullPath, newItem, true);
break;
}
};
break;
case WatcherChangeTypes.Renamed:
backgroundWorker.DoWork += (o, args) =>
{
var fileSystemType = GetFileSystemType(change.FullPath);
var oldItem = Path.Combine(Destination, change.OldName);
var newItem = Path.Combine(Destination, change.Name);
switch (fileSystemType)
{
case FileSystemType.File:
if (File.Exists(oldItem))
File.Move(oldItem, newItem);
break;
case FileSystemType.Directory:
if (Directory.Exists(oldItem))
Directory.Move(oldItem, newItem);
break;
}
};
break;
case WatcherChangeTypes.All:
break;
default:
throw new ArgumentOutOfRangeException();
}
backgroundWorker.RunWorkerAsync();
}
}
}
/// <summary>
/// Files the system watcher configuration created.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="fileSystemEventArgs">The <see cref="FileSystemEventArgs"/> instance containing the event data.</param>
private static void FileSystemWatcherOnCreated(object sender, FileSystemEventArgs fileSystemEventArgs)
{
ChangesQueue.Enqueue(new Change
{
ChangeType = WatcherChangeTypes.Created,
FullPath = fileSystemEventArgs.FullPath,
Name = fileSystemEventArgs.Name
});
}
/// <summary>
/// Files the system watcher configuration deleted.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="fileSystemEventArgs">The <see cref="FileSystemEventArgs"/> instance containing the event data.</param>
private static void FileSystemWatcherOnDeleted(object sender, FileSystemEventArgs fileSystemEventArgs)
{
ChangesQueue.Enqueue(new Change
{
ChangeType = WatcherChangeTypes.Deleted,
FullPath = fileSystemEventArgs.FullPath,
Name = fileSystemEventArgs.Name
});
}
/// <summary>
/// Files the system watcher configuration error.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="errorEventArgs">The <see cref="ErrorEventArgs"/> instance containing the event data.</param>
private static void FileSystemWatcherOnError(object sender, ErrorEventArgs errorEventArgs)
{
var exception = errorEventArgs.GetException();
Console.WriteLine(exception.Message);
}
/// <summary>
/// Files the system watcher configuration renamed.
/// </summary>
/// <param name="sender">The sender.</param>
/// <param name="fileSystemEventArgs">The <see cref="RenamedEventArgs"/> instance containing the event data.</param>
private static void FileSystemWatcherOnRenamed(object sender, RenamedEventArgs fileSystemEventArgs)
{
ChangesQueue.Enqueue(new Change
{
ChangeType = WatcherChangeTypes.Renamed,
FullPath = fileSystemEventArgs.FullPath,
Name = fileSystemEventArgs.Name,
OldFullPath = fileSystemEventArgs.OldFullPath,
OldName = fileSystemEventArgs.OldName
});
}
/// <summary>
/// Gets the type of the file system.
/// </summary>
/// <param name="fullPath">The full path.</param>
/// <returns></returns>
private static FileSystemType GetFileSystemType(string fullPath)
{
if (Directory.Exists(fullPath))
return FileSystemType.Directory;
if (File.Exists(fullPath))
return FileSystemType.File;
return FileSystemType.NotExistant;
}
}
/// <summary>
/// Type of file system object
/// </summary>
internal enum FileSystemType
{
/// <summary>
/// The file
/// </summary>
File,
/// <summary>
/// The directory
/// </summary>
Directory,
/// <summary>
/// The not existant
/// </summary>
NotExistant
}
/// <summary>
/// Change information
/// </summary>
public class Change
{
/// <summary>
/// Gets or sets the type of the change.
/// </summary>
/// <value>
/// The type of the change.
/// </value>
public WatcherChangeTypes ChangeType { get; set; }
/// <summary>
/// Gets or sets the full path.
/// </summary>
/// <value>
/// The full path.
/// </value>
public string FullPath { get; set; }
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the old full path.
/// </summary>
/// <value>
/// The old full path.
/// </value>
public string OldFullPath { get; set; }
/// <summary>
/// Gets or sets the old name.
/// </summary>
/// <value>
/// The old name.
/// </value>
public string OldName { get; set; }
}
}
From MSDN;
The Windows operating system notifies your component of file changes
in a buffer created by the FileSystemWatcher. If there are many
changes in a short time, the buffer can overflow. This causes the
component to lose track of changes in the directory, and it will only
provide blanket notification. Increasing the size of the buffer with
the InternalBufferSize property is expensive, as it comes from
non-paged memory that cannot be swapped out to disk, so keep the
buffer as small yet large enough to not miss any file change events.
To avoid a buffer overflow, use the NotifyFilter and
IncludeSubdirectories properties so you can filter out unwanted change
notifications.
I have the experience that FileSystemWatcher is not always the most reliable thing to use. You could specify the filter to narrow down the files you are watching (NotifyFilter), or increase the buffer size.
But depending on your requirements you may also want to do it another way, like polling every x seconds to get the list of files. But then you might need to tell us more about your business case.
SHChangeNotifyRegister can be used to get shell notifications.
It should be fixed if you increase the buffer size but its not a practical solution.
Because to make sure it always records everything you would need to make the buffer huge.
And that will effect the performance greatlly.
And i think performance issues could be fixed by implementing multi threading.
I need to disable the language change using alt + shift keys for a text box. I have the function which change the currentCulture but pressing Alt + Shift always switch to the next language even if I set it on the keydown or keyup event.
You must detect Windows OS input language changes and change it to your desired language for your application when it has focus.
So read following articles for detecting Windows OS input language changes:
1. http://msdn.microsoft.com/en-us/library/ms644990(VS.85).aspx
2. http://www.codeproject.com/KB/system/TrayMe.aspx
And then use from following codes to achieve to your goal:
/// <summary>
/// Changing Current Input Language to a next installed language
/// </summary>
public void ChangeInputLanguage()
{
// Nothing to do if there is only one Input Language supported:
if (InputLanguage.InstalledInputLanguages.Count == 1)
return;
// Get index of current Input Language
int currentLang = InputLanguage.InstalledInputLanguages.IndexOf(InputLanguage.CurrentInputLanguage);
// Calculate next Input Language
InputLanguage nextLang = ++currentLang == InputLanguage.InstalledInputLanguages.Count ?
InputLanguage.InstalledInputLanguages[0] : InputLanguage.InstalledInputLanguages[currentLang];
// Change current Language to the calculated:
ChangeInputLanguage(nextLang);
}
/// <summary>
/// Changing current Input Language to a new one passed in the param
/// </summary>
/// <param name="ISOLang">ISO Culture name string code e.g. "en" for English</param>
public void ChangeInputLanguage(string ISOLang)
{
// Convert ISO Culture name to InputLanguage object. Be aware: if ISO is not supported
// ArgumentException will be invoked here
InputLanguage nextLang = InputLanguage.FromCulture(new System.Globalization.CultureInfo(ISOLang));
ChangeInputLanguage(nextLang);
}
/// <summary>
/// Changing current Input Language to a new one passed in the param
/// </summary>
/// <param name="LangID">Integer Culture code e.g. 1033 for English</param>
public void ChangeInputLanguage(int LangID)
{
// Convert Integer Culture code to InputLanguage object. Be aware: if Culture code is not supported
// ArgumentException will be invoked here
InputLanguage nextLang = InputLanguage.FromCulture(new System.Globalization.CultureInfo(LangID));
ChangeInputLanguage(nextLang);
}
/// <summary>
/// Changing current Input Language to a new one passed in the param
/// </summary>
/// <param name="InputLang">New Input Language as InputLanguage object</param>
public void ChangeInputLanguage(InputLanguage InputLang)
{
// Check is this Language really installed. Raise exception to warn if it is not:
if (InputLanguage.InstalledInputLanguages.IndexOf(InputLang) == -1)
throw new ArgumentOutOfRangeException();
// InputLAnguage changes here:
InputLanguage.CurrentInputLanguage = InputLang;
}
I'm trying to apply Bradleys thresholding algorithm in Aforge
Everytime I try to process the image I get the exception below
throw new UnsupportedImageFormatException( "Source pixel format is not
supported by the filter." );
I grayscaled the image using the below method before applying the algorithm
private void button2_Click(object sender, EventArgs e)
{
Grayscale filter = new Grayscale(0.2125, 0.7154, 0.0721);
Bitmap grayImage = filter.Apply(img);
pictureBox1.Image = grayImage;
}
The code for the algorithm call
public void bradley(ref Bitmap tmp)
{
BradleyLocalThresholding filter = new BradleyLocalThresholding();
filter.ApplyInPlace(tmp);
}
I tried the sane image in image processing lab and it did work but not on my system.
Any idea what I'm doing wrong?
I've used the following code to get better information in cases like this. It doesn't fix the problem, but it at least gives more helpful information than AForge does by itself.
namespace AForge.Imaging.Filters {
/// <summary>
/// Provides utility methods to assist coding against the AForge.NET
/// Framework.
/// </summary>
public static class AForgeUtility {
/// <summary>
/// Makes a debug assertion that an image filter that implements
/// the <see cref="IFilterInformation"/> interface can
/// process an image with the specified <see cref="PixelFormat"/>.
/// </summary>
/// <param name="filterInfo">The filter under consideration.</param>
/// <param name="format">The PixelFormat under consideration.</param>
[Conditional("DEBUG")]
public static void AssertCanApply(
this IFilterInformation filterInfo,
PixelFormat format) {
Debug.Assert(
filterInfo.FormatTranslations.ContainsKey(format),
string.Format("{0} cannot process an image "
+ "with the provided pixel format. Provided "
+ "format: {1}. Accepted formats: {2}.",
filterInfo.GetType().Name,
format.ToString(),
string.Join( ", ", filterInfo.FormatTranslations.Keys)));
}
}
}
In your case, you can use it as:
public void bradley(ref Bitmap tmp)
{
BradleyLocalThresholding filter = new BradleyLocalThresholding();
filter.AssertCanApply( tmp.PixelFormat );
filter.ApplyInPlace(tmp);
}
I'm a newbie to WMI and I need to implement RegistryValueChangeEvent in a C# service.
I need an event handler that gets triggered each time any one of a set of registry values is changed. I want behavior similar to the FileSystemWatcher class's Changed event, but for registry values.
If there's some other technique I could use to accomplish the same task, I'd appreciate that as well. My minimum requirement is that it be a better solution than what I have now: polling every 20 seconds and comparing the registry value with the last result.
Please provide example code in your answer. If I can get an example for watching just one registry value, that would be fine.
I need a solution in .Net 2.0
Thanks.
WMI can sometimes be interesting to work with...I think I understand your question, so take a look at the code snippet below and let me know if it's what you're looking for.
// ---------------------------------------------------------------------------------------------------------------------
// <copyright file="Program.cs" company="">
//
// </copyright>
// <summary>
// Defines the WmiChangeEventTester type.
// </summary>
// ---------------------------------------------------------------------------------------------------------------------
namespace WmiExample
{
using System;
using System.Management;
/// <summary>
/// </summary>
public class WmiChangeEventTester
{
/// <summary>
/// Initializes a new instance of the <see cref="WmiChangeEventTester"/> class.
/// </summary>
public WmiChangeEventTester()
{
try
{
// Your query goes below; "KeyPath" is the key in the registry that you
// want to monitor for changes. Make sure you escape the \ character.
WqlEventQuery query = new WqlEventQuery(
"SELECT * FROM RegistryValueChangeEvent WHERE " +
"Hive = 'HKEY_LOCAL_MACHINE'" +
#"AND KeyPath = 'SOFTWARE\\Microsoft\\.NETFramework' AND ValueName='InstallRoot'");
ManagementEventWatcher watcher = new ManagementEventWatcher(query);
Console.WriteLine("Waiting for an event...");
// Set up the delegate that will handle the change event.
watcher.EventArrived += new EventArrivedEventHandler(HandleEvent);
// Start listening for events.
watcher.Start();
// Do something while waiting for events. In your application,
// this would just be continuing business as usual.
System.Threading.Thread.Sleep(100000000);
// Stop listening for events.
watcher.Stop();
}
catch (ManagementException managementException)
{
Console.WriteLine("An error occurred: " + managementException.Message);
}
}
/// <summary>
/// </summary>
/// <param name="sender">
/// The sender.
/// </param>
/// <param name="e">
/// The e.
/// </param>
private void HandleEvent(object sender, EventArrivedEventArgs e)
{
Console.WriteLine("Received an event.");
// RegistryKeyChangeEvent occurs here; do something.
}
/// <summary>
/// </summary>
public static void Main()
{
// Just calls the class above to check for events...
WmiChangeEventTester receiveEvent = new WmiChangeEventTester();
}
}
}
You really don't need WMI, as others have pointed out. I too have used RegistryMonitor with no problems.
If you need an example, there's already example code for the RegistryMonitor on the page itself. Did you scroll down to this bit on the code project:
public class MonitorSample
{
static void Main()
{
RegistryMonitor monitor = new
RegistryMonitor(RegistryHive.CurrentUser, "Environment");
monitor.RegChanged += new EventHandler(OnRegChanged);
monitor.Start();
while(true);
monitor.Stop();
}
private void OnRegChanged(object sender, EventArgs e)
{
Console.WriteLine("registry key has changed");
}
}
Are you limited to WMI?
If not you can use RegNotifyChangeKeyValue wrappers like RegistryMonitor
You'll need to utilize WMI for it. See http://msdn.microsoft.com/en-us/library/aa393035.aspx