2012-02-07 3 views
0

У меня есть программа, которая проверяет изменения в файле, а затем, после изменения файла, она считывает его и обновляет некоторые метки. «Однако он падает, потому что я пытаюсь изменить элементы в потоке из другого потока» ~ Или так я думаю. Есть идеи?Элементы Access Form1 из filesystemeventhandler

using System; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Data; 
using System.Drawing; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Windows.Forms; 
using System.IO; 
using System.Threading.Tasks; 


namespace RoomAutomation 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     public void readfile_Click(object sender, EventArgs e) 
     { 

      string[] lines = System.IO.File.ReadAllLines(@"C:\Users\Dandrews\control.txt"); 
      FileSystemWatcher fsw = new FileSystemWatcher(); 
      fsw.Path = @"C:\Users\Dandrews\"; 
      fsw.NotifyFilter = NotifyFilters.LastAccess | NotifyFilters.LastWrite | 
          NotifyFilters.DirectoryName | NotifyFilters.FileName; 
      fsw.Changed += new FileSystemEventHandler(OnChanged); 
      fsw.EnableRaisingEvents = true; 
      if (lines[0] == "1:lights") 
      { 
       Lights.Text = "Lights are on."; 
      } 
      if (lines[0] == "0:lights") 
      { 
       Lights.Text = "Lights are off."; 
      } 
      if (lines[1] == "1:camera") 
      { 
      Camera.Text = "Camera is on."; 
      } 
      if (lines[1] == "0:camera") 
      { 
       Camera.Text = "Camera is off."; 
      } 
      if (lines[2] == "1:speakers") 
      { 
       Speakers.Text = "Speakers are on."; 
      } 
      if (lines[2] == "0:speakers") 
      { 
       Speakers.Text = "Speakers are off."; 
      } 
      if (lines[3] == "1:playlist") 
      { 
       Playlist.Text = "Playlist is on."; 
      } 
      if (lines[3] == "0:playlist") 
      { 
       Playlist.Text = "Playlist is off."; 
      }   
     } 
     private void OnChanged(object source, FileSystemEventArgs e) 
     {    
      Console.Write("Changes"); 
      //Lights.Text = "New label Text"; 

     } 
    } 
} 

`

+0

Какое исключение вы получаете? И * почему * вы ставили кавычки вокруг вашего вопроса? –

+0

@ M.Babcock Да, я заметил, что я быстро прочитал код, чтобы удалить свой комментарий, прежде чем я увидел, что вы ответили на него. :) – warbio

+0

Первое исключение исключения типа «System.InvalidOperationException» произошло в System.Windows.Forms.dll Программа «[6316] RoomAutomation.vshost.exe: Managed (v4.0.30319)» вышла с кодом 0 (0x0). Цитаты вокруг того, что я считаю проблемой. :) – Dandrews

ответ

0

.NET 2.0 и выше doesn't allow you to access UI elements from other threads. Вы должны вызвать вызов кода, который вы хотите запустить в элементе управления. Если вы porting.NET 1,1-код, вот простой хак, чтобы сделать вашу жизнь проще:

http://codebetter.com/jeremymiller/2006/11/06/using-anonymous-methods-with-control-invoke/

+0

Не переносить код .NET 1.1. Ищете легкое обходное решение с использованием .NET 2.0 и новее. – Dandrews

+0

Это/является/легким обходным решением для .NET 2.0 и новее - я упоминаю только о миграции, потому что мне пришлось это делать в прошлом. :-) Менее простым способом было бы использовать [BackgroundWorker] (http://msdn.microsoft.com/en-us/library/cc221403 (v = vs.95) .aspx) –

+0

@ user1116969 Это/is/the простой обходной путь для .NET 2.0 и новее - я упоминаю только о миграции, потому что мне приходилось это делать в прошлом. :-) Независимо от кода, который вы хотели вызвать в своем событии OnChanged в FSW, оберните анонимный делегат и перейдите к методу Invoke вашего элемента формы - приятное и легкое разрешение. Другой вариант - использовать [BackgroundWorker] (http://msdn.microsoft.com/en-us/library/cc221403 (v = vs.95) .aspx) и реализовать событие ProgressChanged, но, пожалуйста, взгляните на то, что подход работает лучше всего для вас. Надеюсь это поможет! –

1

Это потому, что FileSystemWatcher поднимает свои события на Threadpool нити. Естественно, эти события файловой системы происходят асинхронно. Вы не можете напрямую обращаться к компонентам пользовательского интерфейса в обработчике событий, они не являются потокобезопасными. InvalidOperationException там, чтобы напомнить вам, что вы не можете.

Крепление он принимает добавив одну строку кода:

 fsw.SynchronizingObject = this; 

который заставляет FileSystemWatcher маршалу вызов обработчика событий в потоке, который создал форму, поток пользовательского интерфейса. Это не обязательно лучшее решение, есть много накладных расходов, связанных с маршалингом вызова. Но вы будете в порядке с этим решением, так как у вас есть для маршала для каждого события в любом случае с кодом, который у вас есть сейчас.