C# Cross-Thread de communication
dans C#.NET j'ai écrit l'arrière-plan simple thread de travail:
public class MyBackgrounder
{
public delegate void dlgAlert();
public dlgAlert Alert;
public event EventHandler eventAlert;
Thread trd;
public void Start()
{
if (trd == null || trd.ThreadState == ThreadState.Aborted)
{
trd = new Thread(new ThreadStart(Do));
}
trd.IsBackground = true;
trd.Priority = ThreadPriority.BelowNormal;
trd.Start();
}
void Do()
{
Thread.Sleep(3000);
Done();
}
void Done()
{
if (Alert != null)
Alert();
if (eventAlert != null)
eventAlert(this, new EventArgs());
Kill();
}
public void Kill()
{
if (trd != null)
trd.Abort();
trd = null;
}
}
static class Program
{
[STAThread]
static void Main()
{
MyBackgrounder bg = new MyBackgrounder();
bg.eventAlert += new EventHandler(bg_eventAlert);
bg.Alert = jobDone;
bg.Start();
}
static void bg_eventAlert(object sender, EventArgs e)
{
//here, current thread's id has been changed
}
static void jobDone()
{
//here, current thread's id has been changed
}
}
Il attends 3 secondes (fait son travail) et puis la soulève d'un événement ou d'appeler un délégué. il n'y a pas de problème jusqu'ici et tout fonctionne bien. Mais quand j'ai regarder le " Fil.CurrentThread.ManagedThreadId' , je vois que c'est le thread d'arrière-plan! c'est peut-être normal , mais comment puis-je éviter ce problème? si vous testez le " Système.De Windows.Les formulaires.Minuterie composante "et de gérer sesTique de l'événement , vous pouvez voir que le" Fil.CurrentThread.ManagedThreadId' a pas été modifié à partir de principal de l'Id de thread pour rien d'autre.
que puis-je faire?
Système.De Windows.Les formulaires.Minuterie utilise en interne le Windows WM_TIMER événement et simplement compte du nombre de tiques, puis la soulève le .NET de l'événement. Par conséquent, il peut travailler dans le thread principal de processus. L'arrière-plan travailleur, vous ont écrit des œuvres dans le thread d'arrière-plan (explicitement par la création de nouveaux Thread()), overwise le Fil.Sleep(3000) serait de suspendre l'intégralité de votre application. Quel est le problème de cette exécution dans le thread d'arrière-plan exactement?
lorsque l'arrière-plan travailleur objet soulève son événement ou les appels de la méthode spécifiée, là, je vois que le changement de l'id de thread. cela signifie que mon fond travailleur a appelé ces méthodes.
Thats droit, les méthodes appelées ne sont pas dans le contexte de thread de travail, mais dans le fil qui fournit ces rappels.
Merci. Je veux résoudre (changer) le fond de travailleur comportement , donc je l être sûr, plus tard, l'interaction des éléments de l'INTERFACE. il semble que je dois écrire le Document d'information à l'aide de native Win Api, tout comme .NET de la Minuterie, non? mais la façon dont il fonctionne de façon indépendante de la classe sans l'aide de fils!?
OriginalL'auteur losingsleeep | 2012-06-30
Vous devez vous connecter pour publier un commentaire.
Si Vous utilisez Windows Forms, vous pouvez faire quelque chose comme ceci:
Dans votre Formulaire ajouter une propriété
Dans Votre constructeur de définir la propriété
Utiliser cette propriété pour le passer à Votre arrière-plan travailleur comme un paramètre de constructeur. De cette façon, votre travailleur savoir à propos de votre interface contexte. Créer des propriétés similaires à l'intérieur de Votre arrière-plan travailleur.
Changer votre
Done()
méthode:Dans DoneSynchronized Vous devriez toujours être dans Votre thread GUI.
Vrai que! J'ai changé les propriétés.
Merci, je vais essayer...
pour votre aide, mais si je décide d'avoir une référence à un "Système.De Windows.Les formes" dans ma couche sous-jacente , ne pensez-vous pas qu'il est préférable d'utiliser le "Timer" composant au lieu de "WindowsFormsSynchronizationContext"? je l'ai testé et il fonctionne très bien , cause de la top application en cours d'exécution est un formulaire windows. je pense que c'est plus facile à utiliser.
veuillez prendre un coup d'oeil à ma propre réponse. merci beaucoup pour votre aide, mon ami.
OriginalL'auteur Grzegorz W
Le Minuteur s'exécute dans le thread principal (et d'être en retard à aller hors si le thread principal est très occupé). Si, pour une raison quelconque vous souhaitez jobDone() est appelée depuis le thread principal vous pouvez par exemple utiliser un objet BackGroundWorker qui est vissé à l'interne et a certains des événements spécifiques qui sont appelés threads avec le thread principal (permettant de l'INTERFACE utilisateur des mises à jour etc.)
OriginalL'auteur IvoTops
Qu'est-ce exactement est-ce qui vous dérange avec le thread d'arrière-plan? Ce que vous décrivez, a l'air bien pour moi jusqu'à présent.
La
System.Windows.Forms.Timer
que vous avez vérifié pour la comparaison pourrait être en cours d'exécution sur le thread d'INTERFACE utilisateur, qui, de fait, serait un non-thread d'arrière-plan.Partir de la documentation MSDN de la Fil de discussion.IsBackground propriété (faits par moi):
OriginalL'auteur Jens H
Comment au sujet de cette conception:
Créer un EventWaitHandle objet dans votre Formulaire.
Dans un événement de Minuterie gestionnaire d'effectuer les opérations suivantes:
Passer la référence à layer2changed à layer1/layer2 etc. dans leurs constructeurs.
À chaque fois que votre méthode Done() fait quelque chose qui nécessite la mise à jour de l'INTERFACE utilisateur signaler un événement:
Toutefois, veuillez noter qu'il y aura de la différence de temps entre les modifications de la layer2 et de l'INTERFACE utilisateur (plus la Forme.Intervalle de minuterie - le plus la différence).
Note pour tout le monde: c'soley une solution émergents à partir des exigences supplémentaires spécifiées par losingsleep dans les commentaires à sa question. Veuillez les lire avant downvoting. 🙂
OriginalL'auteur Kuba Wyrostek
Je pense qu'il y a une autre solution qui n'a pas besoin d'une référence à "le Système de.De Windows.Les formes" dans la couche sous-jacente (layer2):
layer1 (UI forme) offre un délai d'attente de la mise en œuvre que layer2 pouvez utiliser.
il y a une Interface:
et la classe ouvrière dans Layer2:
et à l'INTERFACE utilisateur, nous avons ceci:
Je remarque que mon scénario de nouveau:
J'ai un projet d'application windows (couches 1) qui utilise une base de projet (layer2) pour faire quelques travaux. les besoins de base non-délai de blocage des contrôles au cours de certaines de ses méthodes, sans la création d'un thread différent , cause après la temporisation, il doit interagir avec l'INTERFACE utilisateur de nouveau. désolé si je ne peux pas en dire plus parce que c'est un peu complexe (pour moi!).
Oui Grzegorz. Dans cet exemple, à l'exception de la Minuterie composant tout ce qui bloque, et ce n'est pas un problème pour moi. je voulais juste utiliser un délai d'attente, sans créer un autre thread.
OriginalL'auteur losingsleeep