C# 子线程完成后,主线程不继续
我正在尝试在我的应用程序中使用多线程。方法C# 子线程完成后,主线程不继续,c#,multithreading,manualresetevent,waitone,countdownevent,C#,Multithreading,Manualresetevent,Waitone,Countdownevent,我正在尝试在我的应用程序中使用多线程。方法test5尝试从Internet获取一些内容,而main线程在继续其他工作之前等待所有线程完成 但是我的main线程在调用test5后没有返回,我的控制台行在内部完成和线程都恢复了从未到达 我如何解决这个问题 class Program { static void Main(string[] args) { string[] url = { "http://...", "http:/
test5
尝试从Internet获取一些内容,而main
线程在继续其他工作之前等待所有线程完成
但是我的main
线程在调用test5
后没有返回,我的控制台行在内部完成代码>和线程都恢复了代码>从未到达
我如何解决这个问题
class Program
{
static void Main(string[] args)
{
string[] url =
{
"http://...", "http://...", "http://...", "http://...", "http://..."
};
test5(url);
Console.WriteLine("thread all got back!!");
// Do some other work after all threads come back
Console.ReadLine();
}
private static void test5(string[] _url)
{
int numThreads = _url.Length;
ManualResetEvent resetEvent = new ManualResetEvent(false);
int toProcess = numThreads;
for (int i = 0; i < numThreads - 1; i++)
{
new Thread( delegate() {
testWebWorking(_url[i]);
if (Interlocked.Decrement(ref toProcess) == 0)
resetEvent.Set();
}).Start();
}
resetEvent.WaitOne();
Console.WriteLine("Done inside!!");
}
private static void test6(string[] _url)
{
int numThreads = _url.Length;
var countdownEvent = new CountdownEvent(numThreads);
for (int i = 0; i < numThreads - 1; i++)
{
new Thread(delegate() {
testWebWorking(_url[i]);
countdownEvent.Signal();
}).Start();
}
countdownEvent.Wait();
Console.WriteLine("Done inside!!");
}
private static void testWebWorking(object url)
{
Console.WriteLine("start {0}", Thread.CurrentThread.ManagedThreadId);
string uri = (string)url;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.KeepAlive = true;
request.Timeout = 5000;
request.ReadWriteTimeout = 5000;
request.Proxy = null;
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
//Console.WriteLine(response.ContentType + "; uri = " + uri);
Stream receiveStream = response.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
// Pipes the stream to a higher level stream reader with the required encoding format.
StreamReader readStream = new StreamReader(receiveStream, encode);
//Console.WriteLine("\r\nResponse stream received.");
Char[] read = new Char[256];
// Reads 256 characters at a time.
int count = readStream.Read(read, 0, 256);
//Console.WriteLine("HTML...\r\n");
String str = "";
while (count > 0)
{
// Dumps the 256 characters on a string and displays the string to the console.
str = new String(read, 0, count);
//Console.Write(str);
count = readStream.Read(read, 0, 256);
}
//Console.WriteLine(str);
// Releases the resources of the response.
response.Close();
// Releases the resources of the Stream.
readStream.Close();
Console.WriteLine("end {0}", Thread.CurrentThread.ManagedThreadId);
}
}
catch (WebException ex)
{
//Console.WriteLine(ex.GetBaseException().ToString() );
//Console.WriteLine(url);
Console.WriteLine("time out !!");
}
finally
{
request.Abort();
request = null;
GC.Collect();
}
}
}
类程序
{
静态void Main(字符串[]参数)
{
字符串[]url=
{
"http://...", "http://...", "http://...", "http://...", "http://..."
};
test5(url);
WriteLine(“线程全部返回!!”;
//在所有线程返回后执行其他一些工作
Console.ReadLine();
}
私有静态void test5(字符串[]\u url)
{
int numThreads=\u url.Length;
ManualResetEvent resetEvent=新的ManualResetEvent(错误);
int-toProcess=numThreads;
for(inti=0;i0)
{
//将256个字符转储到字符串中,并将该字符串显示到控制台。
str=新字符串(读取,0,计数);
//控制台写入(str);
count=readStream.Read(Read,0,256);
}
//控制台写入线(str);
//释放响应的资源。
response.Close();
//释放流的资源。
readStream.Close();
WriteLine(“end{0}”,Thread.CurrentThread.ManagedThreadId);
}
}
捕获(WebException ex)
{
//WriteLine(例如GetBaseException().ToString());
//Console.WriteLine(url);
Console.WriteLine(“超时!!”);
}
最后
{
request.Abort();
请求=null;
GC.Collect();
}
}
}
看看这个:
for (int i = 0; i < numThreads - 1; i++)
在这里,您将在委托中捕获变量i
,因此当您执行它时,它将具有i
所具有的任何值。您可以多次测试同一URL,并跳过其他URL。相反,您应该将i
的值复制到循环中的变量中,以便每次捕获不同的变量:
// Fixed the loop boundary as well
for (int i = 0; i < numThreads; i++)
{
int copy = i;
new Thread(() => // Use a lambda expression for brevity
{
// Fix naming convention for method name, too...
TestWebWorking(_url[copy]);
if (Interlocked.Decrement(ref toProcess) == 0))
{
resetEvent.Set();
}
}).Start()
}
或者,使用Parallel.ForEach
会更简单,它正是为这类事情而设计的。谢谢,它工作得很好。这只是在演示我的问题,所以我只是用for循环来展示它。在实际代码中,我使用了多个while循环,因为实际情况有点复杂。在我的实际代码中,numThreads**是未知的,我在彼此之间有多个while循环**直到所有循环完成,numThreads才知道…如何解决它?我应该在完成所有复杂的while循环后启动线程吗?或者我可以在循环中启动线程,如上图所示?
// Fixed the loop boundary as well
for (int i = 0; i < numThreads; i++)
{
int copy = i;
new Thread(() => // Use a lambda expression for brevity
{
// Fix naming convention for method name, too...
TestWebWorking(_url[copy]);
if (Interlocked.Decrement(ref toProcess) == 0))
{
resetEvent.Set();
}
}).Start()
}
private static void TestWithResetEvent(string[] urls)
{
ManualResetEvent resetEvent = new ManualResetEvent(false);
int counter = urls.Length;
foreach (string url in urls)
{
string copy = url;
Thread t = new Thread(() =>
{
TestWebWorking(copy);
if (Interlocked.Decrement(ref toProcess) == 0))
{
resetEvent.Set();
}
});
t.Start();
}
resetEvent.WaitOne();
Console.WriteLine("Done inside!!");
}