当前位置: 首页 > 知识库问答 >
问题:

当不需要线程池时处理异步/等待

庞乐池
2023-03-14

我正在为一个大型应用程序编写自动化测试。这些测试中的一些很容易成为<code>异步,它只提供<code>async

测试应用程序的一些关键方面如下:

  • 这是一个巨大的ASP.NET应用程序(尽管代码在通过单元测试执行时没有在ASP.NET上下文中运行)。
  • 在其核心中,它严重依赖于每个线程缓存上下文信息(例如活动用户的整个权限方案)的静态对象。

现在,我的问题是当在async方法中使用wait时,延续可能发生在与以前不同的线程中(如this或this等答案中所述)。显然,另一个线程没有上述缓存的上下文信息,一旦我调用任何东西,我就会立即淹没在异常中。

现在,如果我使用< code>GetAwaiter()。GetResult()(如这里所建议的)而不是HTTP调用上的< code>await并使我的测试方法同步,对我的测试用例来说一切似乎都很好。

这个解决方案能可靠地确保我的整个测试用例在同一个线程上运行吗?还是我必须选择一个看似更复杂的解决方案,例如实现自定义同步上下文?

编辑:要明确的是:改变应用程序核心本身的架构,无论其设计是否值得怀疑,都不是一个选项。

要明确第二点:我想调用的<code>异步

EDIT2:这是我的测试方法的简化版本,可以了解其中的调用类型:

[Test]
public async Task TestWriteAsync()
{
    MyAppLogic.Initialize(TestConstants.TestUserId);
    MyAppLogic.CleanUp();

    using (var client = new HttpClient())
    {
        var content = ... // my input data
        var response = await client.PostAsync("http://my.web.app.com/application/write", content);
        Assert.IsTrue(response.IsSuccessStatusCode);

        Assert.AreEqual(..., MyAppLogic.GetValue());

        MyAppLogic.CleanUp();
    }
}

似乎有效的暂定重写:

[Test]
public void TestWrite()
{
    MyAppLogic.Initialize(TestConstants.TestUserId);
    MyAppLogic.CleanUp();

    using (var client = new HttpClient())
    {
        var content = ... // my input data
        var response = client.PostAsync("http://my.web.app.com/application/write", content).GetAwaiter().GetResult();
        Assert.IsTrue(response.IsSuccessStatusCode);

        Assert.AreEqual(..., MyAppLogic.GetValue());

        MyAppLogic.CleanUp();
    }
}

共有1个答案

毋城
2023-03-14

在其核心中,它严重依赖于每个线程缓存上下文信息(例如,活动用户的整个权限方案)的静态对象。

也许,您可以使这些静态对象成为< code>AsyncLocal

但是,如果只允许您接触测试,而不允许您接触正在测试的代码,那么您必须坚持使用同步方法,正如Marc在评论中提到的那样。您应该仍然能够使用<code>HttpClient.PostAsync(..).GetAwaiter()。GetResult(),而不是HttpWebRequest。如果您担心HttpClient中的某些内容可能会导致死锁,您可以使用任务包装调用。运行

Task.Run(() => client.PostAsync(..)).GetAwaiter().GetResult()

但是请注意,在ASP.NET环境中没有线程关联,即您的ASP.NET控制器方法很可能每次都在不同的线程上被调用。因此,这些静态的每线程对象可能只对特定HTTP请求/响应的范围有效。

 类似资料:
  • 线程中使用 java.lang.Runnable 如果用户在代码中通过 java.lang.Runnable 新启动了线程或者采用了线程池去异步地处理一些业务,那么需要将 SOFATracer 日志上下文从父线程传递到子线程中去,SOFATracer 提供的 com.alipay.common.tracer.core.async.SofaTracerRunnable 默认完成了此操作,大家可以按照

  • 在MSDN中,有这样一段话: 但我不知道加粗文字的确切含义,所以我似乎不需要更多的帮助。那么,为什么它在不使用线程的情况下变为异步呢? 来源:http://msdn.microsoft.com/en-us/library/hh191443.aspx

  • 我有一组从基类继承的命令。基类有以下声明: 此异步方法缺少“await”运算符,将同步运行。考虑使用'await'运算符来等待非阻塞API调用,或者使用'await task.run(...)'在后台线程上执行CPU绑定的工作。 显式提供任务完成返回值是否正确?

  • 我最近阅读了有关async/await的文章,我感到困惑的是,我阅读的许多文章/帖子都指出,在使用async await(示例)时不会创建新线程。 我创建了一个简单的控制台应用程序来测试它 以下代码的输出是: 我想知道,如果没有创建其他线程,部分在哪里运行?如果它运行在同一个线程上,难道它不应该因为长的I/O请求而阻塞它吗?或者编译器足够聪明,如果它需要太长的时间,就可以将该操作移到另一个线程上,

  • 我有一个图像路径列表,我想在进程或线程之间划分,以便每个进程处理列表的某些部分。处理包括从磁盘加载图像,进行一些计算并返回结果。我正在使用Python 2.7 下面是我如何创建辅助进程 我所面临的问题是,当我在initializer函数中记录初始化时间时,我知道worker不是并行初始化的,而是每个worker都以5秒的间隔初始化,下面是供参考的日志 我尝试过使用将同时启动辅助线程 我知道Wind

  • 正在使用和原始人的线程吗? 许多月前,我学会了如何在Android上编写多线程Java代码。我记得我必须创建线程、启动线程等等。 现在我正在学习Javascript,我刚刚学习了和。 例如: 这看起来比我以前做的简单多了,而且更直观。 将首先启动,然后启动快速函数(),然后将等待,直到两个函数在日志记录之前解决-和和可能同时运行。我希望这最终取决于浏览器是否是独立的线程。但看起来它走路和说话就像粗