对于C#来说,我很新,但我一直在玩它来学习。到目前为止,我有一个很好的应用程序,可以启动屏幕保护程序并控制Windows系统的音量。跨线程操作无效:从其创建的线程以外的线程访问控制'Form1'
但是我有一些麻烦,我不知道什么是错的。我已经在网站上看到了一些类似的问题,但我认为它们中的任何一个都不适用于我的具体情况。
所以我想从网络上控制应用程序。我的计划是让应用程序每隔几秒钟在我的网站上检查一个网页。根据网站返回的内容,应用会执行不同的操作(静音,启动等),并将网站上的命令重置为空白。网站命令部分都是用PHP完成的,非常简单,这部分内容没有问题。
我创建了一个按钮,调用一个检查页面并执行操作的函数。它运行良好。但是当我试图让它自动检查网站,我得到的错误。我很确定这是因为我将检查和执行操作移到了新线程中。所以我们来看看代码。这些不是完整的文件,但我认为你需要知道的帮助。如果您需要更多,请告诉我。
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);
}
好吧所以基本上静音功能要求窗口句柄才能工作。但是,当我尝试从新线程获取窗口句柄时,它会引发错误:
Cross-thread operation not valid: Control 'Form1' accessed from a thread other than the thread it was created on.
那么我该如何解决这个问题?我在这里阅读了其他答案,说您需要使用Invoke或Delegate,但我不确定这些工作如何或在何处使用它们。我试图按照其中一个答案,但我得到了更多的错误。
http://stackoverflow.com/q/142003/413032你怎么会这么上搜索? –
请不要直接使用'Thread's。对于长时间运行的I/O绑定操作,请使用async/await。对于长时间运行的CPU绑定操作,请使用“任务”。 –
感谢教我如何谷歌....你认为我发现这个网站?我经历了大约7个其他类似的问题,但都没有成功。所以我问我自己的问题就像它告诉我要做的一样。 – mitchelltrout