Reputation: 1059
This is my first time trying to implement a GUI using Windows Forms.
I have a question specific to my project but I will instead use another example that highlights my frustration:
Goal: A program that loop through a file directory and prompt users to rename its folders or not.
So say we have a button:
Start Service
Once the user hits this button the program does all its magic of looping through a directory. So say we have a directory:
A
- 1
- 2
B
-1
So say we only are looping through the top level directory the first folder we come up to in our loop is 'A'.
What I want is the flow of execution to halt here.
There are two more buttons above the 'Start Service button':
Rename
Ignore
I want the execution to halt until one of those two buttons are selected and then certain things happen depending on what the user selects.
I am having trouble with the 'halting' part of this. The last thing I tried:
ManualResetEvent mre = new ManualResetEvent(false);
In start service:
for (... some loop that goes through the directory){
var x = somethign[1] // "A";
mre.WaitOne();
}
In the function for the Rename Button Click Event:
//do some things
mre.Set();
But my form freezes up and it is not working properly. I am sure that this is possible and I just cant seem to figure it out. Can anyone point me in the right direction?
Upvotes: 1
Views: 1329
Reputation: 8031
You need to create a new thread to put the logic in, right now your UI is blocking because you are doing this in your main thread.
So the process is:
Sample code to get you started: Pause/Resume thread whith AutoResetEvent
Full working example
Form1.cs
using System;
using System.IO;
using System.Threading;
using System.Windows.Forms;
namespace ThreadLockExample
{
public partial class Form1 : Form
{
public static ManualResetEvent mre = new ManualResetEvent(true);
public Form1()
{
InitializeComponent();
}
private void btnStartService_Click(object sender, EventArgs e)
{
btnRename.Enabled = false;
btnIgnore.Enabled = false;
Thread thread = new Thread(CheckFiles);
thread.Start();
}
public void CheckFiles()
{
var files = Directory.GetFiles("c:\\"); //Demo Purposes...
foreach (var file in files)
{
Thread.Sleep(500);
mre.Reset();
//Since we are not in our main thread, we need to communicate
//with the static form variable via an invoke on that Form object.
this.Invoke((Action) delegate
{
Program.form1.lstDirectories.Items.Add(file);
Program.form1.lstDirectories.Refresh();
Program.form1.btnRename.Enabled = true;
Program.form1.btnIgnore.Enabled = true;
});
mre.WaitOne();
}
}
private void btnRename_Click(object sender, EventArgs e)
{
//Do whatever you need to do here, then resume thread.
mre.Set();
}
private void btnIgnore_Click(object sender, EventArgs e)
{
//Do whatever you need to do here, then resume thread.
mre.Set();
}
}
}
Program.cs
using System;
using System.Windows.Forms;
namespace ThreadLockExample
{
static class Program
{
public static Form1 form1 = new Form1();
[MTAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.Run(form1);
}
}
}
Upvotes: 2
Reputation: 39132
Here's another example:
public partial class Form1 : Form
{
private bool Rename = false;
private string RenameTo = "";
private BackgroundWorker bgw;
private ManualResetEvent mre = new ManualResetEvent(false);
public Form1()
{
InitializeComponent();
bgw = new BackgroundWorker();
bgw.WorkerReportsProgress = true;
bgw.DoWork += Bgw_DoWork;
bgw.ProgressChanged += Bgw_ProgressChanged;
bgw.RunWorkerCompleted += Bgw_RunWorkerCompleted;
this.Load += Form1_Load;
}
private void Form1_Load(object sender, EventArgs e)
{
btnIgnore.Enabled = false;
btnRename.Enabled = false;
}
private void btnStart_Click(object sender, EventArgs e)
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
if (fbd.ShowDialog() == DialogResult.OK)
{
btnStart.Enabled = false;
progressBar1.Value = 0;
progressBar1.Enabled = true;
bgw.RunWorkerAsync(fbd.SelectedPath);
}
}
private void Bgw_DoWork(object sender, DoWorkEventArgs e)
{
string folder = (string)e.Argument;
DirectoryInfo di = new DirectoryInfo(folder);
DirectoryInfo[] folders = di.GetDirectories();
for(int i = 0; i < folders.Length; i++)
{
mre.Reset();
Rename = false;
DirectoryInfo subFolder = folders[i];
bgw.ReportProgress((int)((decimal)(i + 1) / (decimal)folders.Length * (decimal)100), subFolder.Name);
mre.WaitOne();
if (Rename)
{
Console.WriteLine("Rename `" + subFolder.Name + "` to `" + RenameTo + "`");
}
}
}
private void Bgw_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
progressBar1.Value = e.ProgressPercentage;
lblFolder.Text = (string)e.UserState;
btnIgnore.Enabled = true;
btnRename.Enabled = true;
}
private void btnIgnore_Click(object sender, EventArgs e)
{
btnIgnore.Enabled = false;
btnRename.Enabled = false;
mre.Set();
}
private void btnRename_Click(object sender, EventArgs e)
{
string newName = txtFolder.Text.Trim();
if (newName.Length > 0)
{
Rename = true;
RenameTo = newName;
btnIgnore.Enabled = false;
btnRename.Enabled = false;
mre.Set();
}
else
{
MessageBox.Show("Please enter a New Folder Name first!");
}
}
private void Bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
MessageBox.Show("Done!");
btnStart.Enabled = true;
btnIgnore.Enabled = false;
btnRename.Enabled = false;
progressBar1.Enabled = false;
}
}
Upvotes: 1