C# creating a queue to handle jobs triggered by FileSystemWatcher
- by John S
I have built a small tray app that will watch a folder and when a new file is added it runs a job. The job is to watch for video files and convert them to .mp4 using handBrakeCli. I have all this logic worked out. The problem I run into is that if there is more than one file I want it to queue the job til the prior one is complete. I am fairly new to c# and I am not sure of the best way to handle this.
one idea is to create a queue somehow, a file to store the commands in order maybe, then execute the next one after the process is complete. We are dealing with large movie files here so it can take a while. I am doing this on a quad core with 8gb of RAM and it seems to generally take about 30mins to complete a full length movie.
here is the code I have so far. there are some bits in here that are for future functionality so it refers to some classes that you wont see but it doesnt matter as they arent used here. any suggestions are welcome.
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 System.IO;
using System.Diagnostics;
using System.Threading;
namespace movie_converter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string hbCli;
string cmd;
string file;
string strfilter = "*.*";
string[] filter = new string[3] { ".mkv", ".avi", ".wmv" }; //static list of types
List<string> Ext = new List<string>(); //list of extensions to watch (dynamic)
NotifyIcon notifyIcon = new System.Windows.Forms.NotifyIcon();
private void SetUpTrayIcon()
{
notifyIcon.BalloonTipText = "Movie Converter is running minimized.";
notifyIcon.BalloonTipTitle = "I'm still here";
notifyIcon.Text = "John's movie converter";
notifyIcon.Icon = new Icon(@"C:\\Users\\John\\Pictures\\appicon.ico");
notifyIcon.Click += new EventHandler(notifyIcon_Click);
if (notifyIcon != null)
{
notifyIcon.Visible = true;
notifyIcon.ShowBalloonTip(2000);
}
}
private void Form_Resize(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
{
this.Hide();
SetUpTrayIcon();
}
}
private void notifyIcon_Click(object sender, EventArgs e)
{
this.Show();
this.WindowState = FormWindowState.Normal;
notifyIcon.Visible = false;
}
public void Watcher()
{
FileSystemWatcher watcher = new FileSystemWatcher();
watcher.Path = textBox1.Text + "\\"; //path to watch
watcher.Filter = strfilter; //what types to look for set to * and i will filter later as it cant accept an array
watcher.NotifyFilter = NotifyFilters.FileName | NotifyFilters.DirectoryName; //properties to look at
watcher.IncludeSubdirectories = true; //scan subdirs
watcher.Created += new FileSystemEventHandler(OnChanged);
//TODO: make this only run if the files are of a certain type
watcher.EnableRaisingEvents = true; // start the watcher
}
static bool IsFileLocked(FileInfo file)
{
FileStream stream = null;
try
{
stream = file.Open(FileMode.Open,
FileAccess.ReadWrite, FileShare.None);
}
catch (IOException)
{
//the file is unavailable because it is:
//still being written to
//or being processed by another thread
//or does not exist (has already been processed)
return true;
}
finally
{
if (stream != null)
stream.Close();
}
//file is not locked
return false;
}
// Define the event handlers.
private void OnChanged(object source, FileSystemEventArgs e)
{
string sFile = e.FullPath;
//check that file is available
FileInfo fileInfo = new FileInfo(sFile);
while (IsFileLocked(fileInfo))
{
Thread.Sleep(500);
}
if (System.Diagnostics.Process.GetProcessesByName("HandBrakeCLI").Length != 0)
{
Thread.Sleep(500);
}
else
{
//hbOptions hbCl = new hbOptions();
//hbCli = hbCl.HbCliOptions();
if (textBox3.Text != "")
{
hbCli = textBox3.Text.ToString();
}
else
{
hbCli = "-e x264 -q 20 -B 160";
}
string t = e.Name;
string s = t.Substring(0, t.Length - 4); //TODO: fix this its not reliable
file = e.FullPath;
string opath = textBox1.Text.ToString();
cmd = "-i \"" + file + "\" -o \"" + opath + "\\" + s + ".mp4\" " + hbCli;
try
{
for (int i = 0; i < Ext.Count(); i++)
{
if (e.Name.Contains(Ext[i]))
{
Process hb = new Process();
hb.StartInfo.FileName = "D:\\Apps\\Handbrake\\Install\\Handbrake\\HandBrakeCLI.exe";
hb.StartInfo.Arguments = cmd;
notifyIcon.BalloonTipTitle = "Now Converting";
notifyIcon.BalloonTipText = file;
notifyIcon.ShowBalloonTip(2000);
hb.Start();
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
private void button1_Click(object sender, EventArgs e) //ok button
{
//add each array item to the list
for (int i = 0; i < filter.Count(); i++)
{
Ext.Add(filter[i]);
}
if (textBox1.Text != "" && textBox1.Text.Length > 2)
{
Watcher(); //call watcher to run
}
this.WindowState = FormWindowState.Minimized;
}
private void button2_Click(object sender, EventArgs e) //browse button
{
//broswe button
DialogResult result = folderBrowserDialog1.ShowDialog();
if (result == DialogResult.OK)
{
textBox1.Text = folderBrowserDialog1.SelectedPath;
}
}
private void button3_Click(object sender, EventArgs e) //commands button
{
Process np = new Process();
np.StartInfo.FileName = "notepad.exe";
np.StartInfo.Arguments = "hbCLI.txt";
np.Start();
}
private void button4_Click(object sender, EventArgs e) //options button
{
hbOptions options = new hbOptions();
options.ShowDialog();
}
private void button5_Click(object sender, EventArgs e) //exit button
{
this.Close();
}
private void Form1_Load(object sender, EventArgs e)
{
this.Resize += Form_Resize;
}
}
}