2

我在多线程和事件方面遇到了一些问题。

我有以下在几个线程中执行的函数:

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);
            }
        }));
    };
}

它被这样调用:

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

我面临的问题(我认为)是,之后

connectionManager.GetProjectInfo(filter);

我的线程取消。我收到一个 AggregateException,它告诉我任务已关闭,所以我想这一定是问题所在。我想要实现的是以下。我的函数,因此当前线程,必须阻塞,直到该事件被触发:

connectionManager.InfoReceived += ...

有什么解决办法吗?你能给我一些代码吗?

编辑:

这是 GetProjectInfo 方法:

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());
        }
    }

我在那里得到了 AggregateException。

这是一个例外:

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: 
4

1 回答 1

1

AggregateExceptions are thrown by Tasks, but you are using Threads ??

Anyway, to block the thread until the event handler has run, you can use a 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();
}
于 2012-04-10T10:28:27.173 回答