2012-04-10 7 views
2

Ich habe einige Probleme mit Multithreading und Events.Multithreading und Ereignisse

Ich habe die folgende Funktion, die in einigen Threads ausführt:

private void GetProjectInformation(object obj) 
{ 
    //Casten 
    //string projectName = (string)obj; 
    FilterOptions filter = (FilterOptions)obj; 

    ProjectConnectionManager connectionManager = new ProjectConnectionManager(); 
    connectionManager.GetProjectInfo(filter); 
    connectionManager.InfoReceived += delegate(object sender, ProjectInfoEventArgs e) 
    { 
     //Geupdate resultaat in de collection vervangen 
     int index = 0; 
     bool found = false; 
     m_dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => 
     { 
      foreach (ProjectInfo projectInfo in m_allProjects) 
      { 
       if (String.Equals(projectInfo.ProjectName, e.ProjectInfo.ProjectName)) 
       { 
        found = true; 
        ProjectInfo result = e.ProjectInfo; 
        m_allProjects[index] = e.ProjectInfo; 

        break; 
       } 
       index++; 
      } 

      //Niet gevonden 
      if (!found) 
      { 
       m_allProjects.Add(e.ProjectInfo); 
      } 
     })); 
    }; 
} 

es wie folgt aufgerufen wird:

foreach (FilterOptions opt in m_projectsToShow) 
{ 
    Thread thread = 
       new Thread(new ParameterizedThreadStart(GetProjectInformation)); 
    thread.Start(opt); 
} 

Das Problem, das ich bin vor (glaube ich), ist, dass nach

connectionManager.GetProjectInfo(filter); 

mein Thread bricht ab. Ich bekomme eine AggregateException, die mir sagt, dass eine Aufgabe geschlossen wurde, also denke ich, dass dies das Problem sein muss. Was ich gerne erreichen möchte, ist folgendes. Meine Funktion, also der aktuelle Thread, muss blockieren, bis das Ereignis ausgelöst wurde:

Gibt es eine Lösung für dieses Problem? Kannst du mir bitte einen Code geben?

Edit:

Dies ist die GetProjectInfo Methode:

public void GetProjectInfo(FilterOptions filter) 
    { 
     ProjectInfo result = new ProjectInfo(); 

     try 
     { 
      var task = m_httpClient.PostAsync(string.Format("api/project"), new ObjectContent<FilterOptions>(filter, XmlMediaTypeFormatter.DefaultMediaType)); 
      task.ContinueWith(r => 
      { 
       try 
       { 
        r.Wait(); 
        if (r.Result.IsSuccessStatusCode) 
        { 
         Console.WriteLine("Project " + filter.ProjectName + " was succesfull..."); 

         r.Result.Content.ReadAsAsync<ProjectInfo>().ContinueWith(l => 
         { 
          result = l.Result; 
          OnProjectInfoReceived(new ProjectInfoEventArgs(result)); 
         }); 
        } 
        else 
        { 
         Console.WriteLine("Project " + filter.ProjectName + " failed!"); 
        } 
       } 
       catch (AggregateException ex) 
       { 
        Console.WriteLine(ex.ToString()); 
       } 
      }).Wait(m_httpClient.Timeout); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.ToString()); 
     } 
    } 

Und ich die Aggregate bekommen dort.

Dies ist die Ausnahme:

System.AggregateException was caught 
    Message=One or more errors occurred. 
    Source=mscorlib 
    StackTrace: 
     at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions) 
     at System.Threading.Tasks.Task`1.get_Result() 
     at Dashboard.Utils.ProjectConnectionManager.<>c__DisplayClass8.<GetProjectInfo>b__5(Task`1 r) in C:\Users\xxx\Documents\My Own Documents\xxx\ProjectConnectionManager.cs:line 79 
    InnerException: System.Threading.Tasks.TaskCanceledException 
     Message=A task was canceled. 
     InnerException: 
+0

'm_allProjects' besser eine Thread-sichere Sammlung sein sollte. –

+0

Hat 'GetProjectInfo() 'irgendwie einen anderen Thread? Andernfalls sollten Sie das Ereignis zuerst verbinden. –

+0

Danke Henk, ich sollte mir das auch ansehen. Aber zuerst möchte ich eine Lösung für mein Hauptproblem haben :) –

Antwort

1

AggregateExceptions von Tasks geworfen werden, aber Sie verwenden Threads ??

Wie dem auch sei, den Faden zu blockieren, bis der Event-Handler ausgeführt wurde, können Sie eine ManualResetEvent:

private void GetProjectInformation(object obj) 
{ 
    ... 
    ProjectConnectionManager connectionManager = new ProjectConnectionManager(); 

    var mre = new ManualResetEvent(false); 

    connectionManager.InfoReceived += delegate(...) 
    { 
     ... 
     mre.Set(); 
    }; 

    connectionManager.GetProjectInfo(filter); 

    mre.WaitOne(); 
} 
+0

Ich habe diese Lösung versucht, aber es funktioniert nicht. Was könnte sonst noch falsch sein? –

+0

Jemand anderes? –

+0

Irgendwie könnte ich das Problem lösen, indem ich den .Continue auf 1 Zeile setze und nicht in einer neuen Zeile, wie ich es zuerst getan habe. Sehr seltsame Situation. Danke euch trotzdem !! –