使用 HttpWebRequest 的死锁
Deadlock using HttpWebRequest
我创建了一个使用 WebRequest 请求 10 次 HTTP header 的异步方法。只要 URL 无效,我的程序就可以正常工作。 URL 是否有效,只发送两个请求。
为了检查这一点,我制作了两个按钮,一个用于检查有效 URL,一个用于检查无效 URL。如果我使用有效的 URL,我的计数器正好增加 2,但只是第一次。有趣的是,我仍然可以按下无效 URL 的按钮并且它按预期工作。
这是cs文件:
public partial class MainWindow : Window
{
int counter = 0;
private async Task DoWork(String url)
{
for (int i = 0; i < 10; i++)
{
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "HEAD";
request.Timeout = 100;
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)await request.GetResponseAsync();
}
catch(Exception ex)
{
}
counter++;
Dispatcher.Invoke(() => label.Content = counter);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DoWork("http://www.google.ch");
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
DoWork("http://www.adhgfqliehfvufdigvhlnqaernglkjhr.ch");
}
}
这是 xaml 文件
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Label Name="label" Content="Label" HorizontalAlignment="Left" Margin="78,151,0,0" VerticalAlignment="Top"/>
<Button Content="Valid URL" HorizontalAlignment="Left" Margin="64,71,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<Button Content="Invalid URL" HorizontalAlignment="Left" Margin="144,71,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
</Grid>
</Window>
有人可以解释这种行为吗?
由于异步方法,问题不是预期的死锁。这是因为我没有使用处理 HttpWebResponse。
这里我们找到了这个问题的提示
也解释了为什么它正好工作了两次。连接似乎保持打开状态并且有一个 ConnectionLimit:
System.Net.ServicePointManager.DefaultConnectionLimit
添加 dispose 解决了问题:
try
{
response = (HttpWebResponse)await request.GetResponseAsync();
}
catch (Exception ex)
{
}
finally
{
if (response != null)
{
response.Dispose();
}
}
我创建了一个使用 WebRequest 请求 10 次 HTTP header 的异步方法。只要 URL 无效,我的程序就可以正常工作。 URL 是否有效,只发送两个请求。
为了检查这一点,我制作了两个按钮,一个用于检查有效 URL,一个用于检查无效 URL。如果我使用有效的 URL,我的计数器正好增加 2,但只是第一次。有趣的是,我仍然可以按下无效 URL 的按钮并且它按预期工作。
这是cs文件:
public partial class MainWindow : Window
{
int counter = 0;
private async Task DoWork(String url)
{
for (int i = 0; i < 10; i++)
{
HttpWebRequest request = WebRequest.CreateHttp(url);
request.Method = "HEAD";
request.Timeout = 100;
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)await request.GetResponseAsync();
}
catch(Exception ex)
{
}
counter++;
Dispatcher.Invoke(() => label.Content = counter);
}
}
private void Button_Click(object sender, RoutedEventArgs e)
{
DoWork("http://www.google.ch");
}
private void Button_Click_1(object sender, RoutedEventArgs e)
{
DoWork("http://www.adhgfqliehfvufdigvhlnqaernglkjhr.ch");
}
}
这是 xaml 文件
<Window x:Class="WpfApplication2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Label Name="label" Content="Label" HorizontalAlignment="Left" Margin="78,151,0,0" VerticalAlignment="Top"/>
<Button Content="Valid URL" HorizontalAlignment="Left" Margin="64,71,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
<Button Content="Invalid URL" HorizontalAlignment="Left" Margin="144,71,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click_1"/>
</Grid>
</Window>
有人可以解释这种行为吗?
由于异步方法,问题不是预期的死锁。这是因为我没有使用处理 HttpWebResponse。
这里我们找到了这个问题的提示
也解释了为什么它正好工作了两次。连接似乎保持打开状态并且有一个 ConnectionLimit: System.Net.ServicePointManager.DefaultConnectionLimit
添加 dispose 解决了问题:
try
{
response = (HttpWebResponse)await request.GetResponseAsync();
}
catch (Exception ex)
{
}
finally
{
if (response != null)
{
response.Dispose();
}
}