【问题标题】:Multithreading and events多线程和事件
【发布时间】:2012-04-10 10:11:10
【问题描述】:

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

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

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: 

【问题讨论】:

  • m_allProjects 最好是线程安全的集合。
  • GetProjectInfo() 是否以某种方式启动另一个线程?否则你应该先挂起事件。
  • 谢谢 Henk,我也应该看看。但我首先想解决我的主要问题:)
  • 我编辑了问题并添加了 GetProjectsInfo 方法,该方法本身包含一个任务(异步)。我尝试先连接事件,然后调用 GetProjectInformation(),但问题仍然存在。
  • 我也更新了我的帖子,但也有例外。谢谢

标签: c# multithreading dotnet-httpclient


【解决方案1】:

AggregateExceptionsTasks 抛出,但你使用的是Threads ??

无论如何,要在事件处理程序运行之前阻塞线程,您可以使用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();
}

【讨论】:

  • 我试过这个解决方案,但它不起作用。那么还有什么问题呢?
  • 不知何故,我可以通过将 .Continue 放在 1 行而不是像我第一次那样放在新行中来解决问题。很诡异的情况。总之谢谢大家!!
猜你喜欢
  • 1970-01-01
  • 2013-04-22
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
相关资源
最近更新 更多