2017-07-07 2 views
1

Je dois mettre à jour un programme d'utiliser une version plus récente de Awesomium, spécifiquement 1.7.5Création d'un formulaire qui souscrit à des événements d'un fil de blocage

bien avec la mise à jour Awesomium doit désormais fonctionner sur son propre fil et ça bloque.

Je peux mettre en file d'attente de travail sur le thread de blocage en utilisant WebCore.QueueWork() et cela complétera l'action transmise sur le thread WebCore.Run() a été appelé. Je me suis assuré de lui donner son propre fil donc le reste de mon application ne bloque pas.

La façon dont le programme a fonctionné était de créer un objet de travail qui avait un constructeur qui instanciait un WebView et WebSession en utilisant la bibliothèque WebCore. Il a ensuite créé un formulaire qui accepte un objet worker en tant qu'argument permettant au formulaire de s'abonner aux événements de la bibliothèque WebCore.

var worker = new Worker(); 
var debugForm = new PBForm(worker); 
debugForm.Show(); 

Le constructeur de travail a cette ligne de code qui appelle la fonction SurfaceIsDirty chaque fois que la vue est mise à jour.

((ImageSurface)_view.Surface).Updated += (s, e) => { if (webView_SurfaceIsDirty != null) webView_SurfaceIsDirty(s, e); }; 

Cette fonction est assignée dans le constructeur de formulaire:

this.worker.webView_SurfaceIsDirty = (sender, e) => 
{ 
    ImageSurface buffer = (ImageSurface)this.worker._view.Surface; 
    pictureBox1.Image = buffer.Image; 
}; 

Ainsi, les mises à jour de l'image du formulaire chaque fois que le WebView est mis à jour.

Cela fonctionnait auparavant dans le thread WebCore mais maintenant que le thread WebCore bloque je ne peux pas obtenir ce formulaire pour fonctionner correctement.

Donc c'est où je suis coincé. J'ai besoin d'exécuter le formulaire dans un thread séparé afin qu'il ne se bloque pas simplement parce qu'il est coincé avec le thread WebCore qui bloque.

Mon idée est la suivante:

  1. Lorsqu'un travailleur est créé créer une forme dans un nouveau thread comme une propriété de l'instance des travailleurs.
  2. Lorsqu'un événement WebCore se produit, l'instance de travail doit pouvoir mettre à jour son formulaire.

Il est en cours de compilation, la forme est réactive, mais l'image n'est pas mise à jour et je soupçonne que c'est lié à la forme étant dans un thread différent maintenant. Voici le code approprié que j'ai en ce moment:

J'ai ajouté cette propriété à la catégorie des travailleurs:

public PBForm2 DebugForm; 

J'instancier la classe ouvrière dans le fil de blocage WebCore:

WebCore.QueueWork(AddWorker); 

Dans le AddWorker méthode Je crée un nouveau thread et exécute un formulaire en l'attachant à la propriété worker:

static void AddWorker() 
{ 
    var worker = new Worker(); 
    Workers.Add(worker); 
    new Thread(() => 
    { 
     worker.DebugForm = new PBForm2(worker.Id); 
     var debugForm = new PBForm2(worker.Id); 

     Application.Run(debugForm); 
     Application.DoEvents(); 

    }).Start(); 
} 

Enfin l'événement travailleur lui-même est maintenant:

((ImageSurface)_view.Surface).Updated += (s, e) => 
{ 
    ImageSurface buffer = (ImageSurface)_view.Surface; 
    DebugForm.pictureBox1.Image = buffer.Image; 
    DebugForm.pictureBox1.Refresh(); 
}; 

Il semble très proche de travailler, la forme répond à une interaction utilisateur et les travailleurs font leur chose et le déclenchement d'événements, mais l'image ne change pas dans la forme.L'événement est en train d'être touché et la nouvelle image est là, je soupçonne que le fait que le formulaire se trouve dans un thread différent provoque la mise à jour de l'image sur le formulaire.

C'était un très long post, donc si vous lisez ceci, merci d'avoir pris le temps de passer à travers tout cela. Je suis très novice en ce qui concerne le threading et toutes les suggestions ou liens, ou même ce qu'il faut rechercher pour résoudre ce problème, seraient grandement appréciés.

Répondre

1

j'ai tout compris, après avoir résolu le problème où je mettais le mauvais objet Form (merci Troy Mac1ure) Je suis tombé sur un problème de filetage où je ne pouvais pas accéder à la Imagebox du formulaire à partir du fil Awesomium.

Je l'ai résolu en utilisant une classe d'aide:

public static class ThreadHelper 
{ 
    private delegate void SetPictureCallback(PBForm f, Image image); 
    private delegate void AppendTextCallback(PBForm f, string text); 

    public static void SetPicture(PBForm form, Image image) 
    { 
     if (form.InvokeRequired) 
     { 
      SetPictureCallback d = SetPicture; 
      form.Invoke(d, form, image); 
     } 
     else 
     { 
      form.pictureBox1.Image = image; 
      form.pictureBox1.Refresh(); 
     } 
    } 

    public static void AppendText(PBForm form, string text) 
    { 
     if (form.InvokeRequired) 
     { 
      AppendTextCallback d = AppendText; 
      form.Invoke(d, form, text); 
     } 
     else 
     { 
      form.textBox1.Text += text; 
      form.textBox1.SelectionStart = form.textBox1.TextLength - 1; 
      form.textBox1.ScrollToCaret(); 
      form.textBox1.ScrollToCaret(); 
     } 
    } 
} 

Lorsque l'événement est déclenché dans le thread de travail que j'appelle la fonction de mettre à jour le formulaire:

_view.Surface = new ImageSurface(); 
((ImageSurface)_view.Surface).Updated += (s, e) => 
{ 
    ImageSurface buffer = (ImageSurface)_view.Surface; 
    ThreadHelper.SetPicture(DebugForm, buffer.Image); 
    Application.DoEvents(); 
}; 

_view.ConsoleMessage += (s, e) => 
    ThreadHelper.AppendText(DebugForm, string.Format("{0} : {1} [{2}]\r\n", e.LineNumber, e.Message, e.Source)); 
2

Vous créez deux des mêmes formes:

worker.DebugForm = new PBForm2(worker.Id); 
var debugForm = new PBForm2(worker.Id); 

puis chargement debugForm, mais mises à jour sont en cours pour DebugForm.picturebox1 afin que vos mises à jour ne seront pas vus. Les mises à jour doivent être effectuées dans debugForm.picturebox1, mais vous ne devriez en créer qu'une.

Sans voir tout le code, pourquoi ne pas simplement charger celui dans la classe des travailleurs ou pointer l'un sur l'autre?

Application.Run(worker.DebugForm); 
Application.DoEvents(); 

ou

worker.DebugForm = new PBForm2(worker.Id); 
var debugForm = worker.DebugForm; 

Application.Run(debugForm); 
Application.DoEvents(); 
+0

bien que ce soit réglé un problème, mais conduit à un autre, je ne peux pas accéder à pictureBox1 du formulaire à partir du thread Awesomium dans lequel l'événement est déclenché. Je l'ai fait en créant une classe statique qui appelle la fonction Form.Invoke pour appeler correctement les modifications apportées au formulaire. –