Im pretty new to C# but I have been playing around with it to learn. So far I have a nice app that does things like starts up the screen saver and controls the windows system volume.
However I'm having some trouble and I'm not sure what is wrong. I have already gone through a bunch of similar questions on the site but I don't think any of them apply to my specific case.
So I wanted to control the app from the web. My plan is to have the app check a webpage on my site for a command every couple seconds. Depending on what the site returns the app will do different things(mute, vol up, etc.) and reset the command on the website to blank. The website command part is all done in PHP and is quite simple, there is no problem with that part of it.
I created a button that calls a function that checks the page and performs the action. It worked fine. But when I tried to make it automatically check the site I'm getting errors. I'm pretty sure it is because I moved the check and perform action to a new thread. So lets move on to the code. These are not the full files but what I think you need to know to help. If you need anything more just let me know.
Form1.cs
public Form1(Boolean init = true)
{
if (init)
{
InitializeComponent(); //initialize UI
startWebMonitor(); //starts web monitor thread for remote web commands
}
}
private void startWebMonitor()
{
Thread t = new Thread(WebMonitor.doWork);
t.Start();
}
public IntPtr getWindowHandle()
{
return this.Handle;
}
WebMonitor.cs
public static void doWork()
{
while(true)
{
checkForUpdate();
Thread.Sleep(1000);
}
}
private static void checkForUpdate()
{
lastCommand = getLastCommand();
if (lastCommand.Equals(""))
{
//No Update
}
else
{
processCommand(lastCommand);
}
}
public static void processCommand(String command)
{
if(command.Equals("mute"))
{
VolumeCtrl.mute(Program.form1.getWindowHandle());
}
HTTPGet req2 = new HTTPGet();
req2.Request("http://mywebsite.com/commands.php?do=clearcommand");
}
VolumeCtrl.cs
private static IntPtr getWindowHandle()
{
Form1 form1 = new Form1(false); //false = do not initialize UI again
return form1.getWindowHandle();
}
public static void mute(IntPtr handle)
{
SendMessageW(getWindowHandle(), WM_APPCOMMAND, getWindowHandle(), (IntPtr)APPCOMMAND_VOLUME_MUTE);
}
Alright so basically the mute function requires the window handle in order to work. But when I try to get the window handle from the new thread it throws the error:
Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.
So how do I get around this? I have read other answers on here saying you need to use Invoke or Delegate but I'm not sure how those work or where to use them. I tried to follow one of the answers but I got even more errors.