读书人

【200分】多线程有关问题

发布时间: 2012-02-17 17:50:42 作者: rapoo

【200分】多线程问题
最多只能给到200分了,如果哪位回答得详细的话,再加分(另贴加分也行)
先说下我的要求吧:我希望写一个函数
void Scan(int count, int start, int end)
通过传入线程数,起始端口,来扫描本机打开的端口
这里有两个问题:
1.线程数不等于要扫描的端口数(通常线程数小于端口数)
也就是线程数不等于任务数
2.同步的问题
如果我不做任何同步的处理,结果就有错,比如本来80端口是打开的,检查出来就可能是84端口
用lock做同步不太会,同步后的确不出错了,但是任务是依次执行,而不是并行执行了,多线程就没有任何意义了
我的代码:

C# code
using System.Net.Sockets;using System.Threading;        void Scan(int count, int start, int end)        {            int current = start;            for (int i = 0; i < count; i++)            {                //我习惯使用闭包,也可以用带参数的委托,或者字段来共享数据                Thread th = new Thread(() =>                    {                       // lock (this)  //这样同步不对,失去了多线程的意义了                       // {                            while (current++ <= end)                            {                                try                                {                                    TcpClient tc = new TcpClient();                                    tc.Connect("localhost", current);                                    //已经在窗体装入时:Control.CheckForIllegalCrossThreadCalls = false;                                    //如果不设置这个属性,怎么才能把数据显示在列表框呢?                                    listBox1.Items.Add(current);                                }                                catch { }                            }                       // }                    });                th.IsBackground = true;                th.Start();            }        }调用:Scan(10, 1, 255);


[解决办法]
先来抢个沙发,

要知晓正确答案,请看楼下。。。。。。。。。。。。。
[解决办法]
建议把代码贴全~
[解决办法]
C# code
 private void DoWork(object sender, DoWorkEventArgs e)        {            //模拟进度条            for (int i = 0; i < 10; i ++)            {                Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(() =>                {                    WorkProgress.Value = i*10;                }));                Thread.Sleep(100);            }            try            {                if(strUrl!=string.Empty)                    parseUrl(strUrl);            }            catch            {                    flvUrl="error";            }        }        private void BeforeWork()        {            imageLoad.Visibility = Visibility.Visible;            WorkProgress.Visibility = Visibility.Visible;            WorkProgress.Maximum = 100;            WorkProgress.Minimum = 0;            WorkProgress.Value = 0;            btnGet.IsEnabled = false;            strUrl = textBox1.Text;        }        private void FinsihWork(object sender,RunWorkerCompletedEventArgs e)        {            WorkProgress.Visibility = Visibility.Hidden;            imageLoad.Visibility = Visibility.Hidden;            btnGet.IsEnabled = true;            if (flvUrl != "error")                tbResult.Text = flvUrl;        }
[解决办法]
这么点看不出名堂来
[解决办法]
参考资料C# WinForm开发系列 - Thread/Delegate/Event
[解决办法]
直接这样做事做不到的,TabPage并没有实现IClone接口,无法复制。
我的建议:

你的TabPage1的界面初始化,使用代码来完成,增加一个方法,里面控件的命名要与TabPage1的名称相关联,意在避免命名重复。
TabPage ConstructTabPage()
{
...
}

你如果需要一个tabpage的话,就调用该方法,返回一个,然后将该TabPage添加到TabControl里面就可以了
最好实现预绑定,也就是在构造TabPage的时候,把数据也传进去,如:
TabPage ConstructTabPage(DataTable dt)


{
//初始化TabPage
//初始化控件
//添加到TabPage
//将数据绑定到ListView/DataGrid控件

//返回TabPage
}
[解决办法]
线程问题要顶起!
[解决办法]
不好意思,贴错了。
[解决办法]
current部分有点问题.

我的机子没有装.NET工具,所以只能凭经验回答.
[解决办法]
for (int i = 0; i < count; i++)
{

int current = (end - start) / count * i;
int end2 = (end - start) / count + current;

//我习惯使用闭包,也可以用带参数的委托,或者字段来共享数据
Thread th = new Thread(() =>
{
// lock (this) //这样同步不对,失去了多线程的意义了
// {
while (current++ <= end2)
{
try
{
TcpClient tc = new TcpClient();
tc.Connect("localhost", current);
//已经在窗体装入时:Control.CheckForIllegalCrossThreadCalls = false;
//如果不设置这个属性,怎么才能把数据显示在列表框呢?
listBox1.Items.Add(current);
}
catch { }
}
// }
});
th.IsBackground = true;
th.Start();
}

方便说明问题,这个修改只对扫描范围能被线程数整除,如果不能被整除,还要对current,end2做调整。
[解决办法]

C# code
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Net.Sockets;namespace FtpUpDownLoad{       public partial class Form1 : Form    {        public delegate void MessageHandle(string mssage);        MessageHandle MH ;        int g_count ;//全局 起始端口号        int g_End;//全局 终止端口号        public Form1()        {            InitializeComponent();        }        private void Form1_Load(object sender, EventArgs e)        {            MH = new MessageHandle(ShowMessage);//显示端口号委托            g_count = 0;        }         void Scan(int count, int start, int end)        {            g_Count = start;            g_End = end;            for (int i = 0; i < count; i++)            {                ThreadPool.QueueUserWorkItem(new WaitCallback(ScanPoolItem));//开始一个线程池 循环做 ScanPoolItem            }        }        void ScanPoolItem(object stateInfo)        {            g_count++;            if (g_Count <= g_End)            {                TcpClient tp = new TcpClient();                tp.Connect("localhost", g_Count);                if (!tp.Connected)                {                    this.Invoke(MH, new string[] { Convert.ToString(g_Count) });//异步调用delegate将端口号添加到ListBox                }            }        }        private void ShowMessage(string Msg)        {            this.listBox1.Items.Add(string.Format("The Opened port is  {0}", Msg));        }}
[解决办法]
不过这样也不算优雅,期待优雅的code出现。。
[解决办法]
while (current++ <= end)
这个有问题current被多个线程调用了

在线程中修改界面上的listBox1可以用委托 比如我以前写过的一段
C# code
        delegate void RefreshForm(string s1, string s2);         //主线程外操作界面的方法        private void AddList(string filename, string rowcount)        {            if (listBox1.InvokeRequired)            {                Invoke(new RefreshForm(AddList), filename, rowcount);            }            else            {                    listBox1.Items.Insert(0, DateTime.Now.ToString() + "更新文件" + filename + "---共有记录数" + rowcount + "条");            }        } 


[解决办法]
把闭包弄成内部类吧, 估计优雅点...
[解决办法]
我记得C#好像有个方法可以直接在变量声明的地方锁住它
[解决办法]
抢个少发关注
[解决办法]
试试这个

C# code
int volatile current = start;
[解决办法]
C# code
private volatile int current;        void Scan(int count, int start, int end)        {            current = start;            for (int i = 0; i < count; i++)            {                Thread th = new Thread(() =>                                           {                                               while (current <= end)                                               {                                                   current++;                                                   try                                                   {                                                       TcpClient tc = new TcpClient();                                                       tc.Connect("localhost", current);                                                       addPort(current);                                                   }                                                   catch                                                   {                                                   }                                               }                                           });                th.IsBackground = true;                th.Start();            }        }        private delegate void AddPortHandler(int port);        private void addPort(int port)        {            AddPortHandler aph = addPortInner;            listBox1.Invoke(aph, new object[] {port});        }        private void addPortInner(int port)        {            listBox1.Items.Add(port);        }        private void button1_Click(object sender, EventArgs e)        {            try            {                Scan(5, 0,25535);            }            catch (Exception ex)            {                MessageBox.Show(ex.Message);            }                    }
[解决办法]
探讨
13楼的兄台没理解到

1.线程数不等于要扫描的端口数(通常线程数小于端口数)
也就是线程数不等于任务数


如果每个线程扫描的端口数相等,我们就可以把扫描这若干个端口的整体当作一个任务,所以还是线程数等于任务数
不符合要求
而且扫描某个端口所需的时间也不同,扫描同样数量的端口,每个线程的工作时间不同,不能最大化效率
要是效率最大化,是让每个线程尽可能工作相等的时间,而不是处理相同的任务数

[解决办法]
C# code
private volatile int current;        void Scan(int count, int start, int end)        {            current = start;            for (int i = 0; i < count; i++)            {                Thread th = new Thread(() =>                                           {                                               while (current <= end)                                               {                                                   int scanned = current++;                                                   try                                                   {                                                       TcpClient tc = new TcpClient();                                                       tc.Connect("localhost", scanned);                                                       addPort(scanned);                                                   }                                                   catch                                                   {                                                   }                                               }                                           });                th.IsBackground = true;                th.Start();            }        } 


[解决办法]
修改了一下。。。~

C# code
using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Net.Sockets;using System.Threading;namespace FtpUpDownLoad{    public partial class Form1 : Form    {        public delegate void MessageHandle(string mssage);        MessageHandle MH;        int g_count;//全局 起始端口号        int g_End;//全局 终止端口号        public Form1()        {            InitializeComponent();        }        private void Form1_Load(object sender, EventArgs e)        {            MH = new MessageHandle(ShowMessage);//显示端口号委托            g_count = 0;            Scan(400,22223,50000);        }        void Scan(int count, int start, int end)        {            g_count = start;            g_End = end;            for (int i = 0; i < count; i++)            {                ThreadPool.QueueUserWorkItem(new WaitCallback(ScanPoolItem));//开始一个线程池 循环做 ScanPoolItem            }        }        void ScanPoolItem(object stateInfo)        {            g_count++;                                      if (g_count <= g_End)                {                    TcpClient tp = new TcpClient();                    System.Net.IPEndPoint ep = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("127.0.0.1"), g_count);                    try                    {                        tp.Client.Connect(ep);                    }                    catch                    {                        this.Invoke(MH, new string[] { Convert.ToString(g_count) });//异步调用delegate将端口号添加到ListBox                     }                    finally                    {                        tp.Client.Close();                    }                }                    }        private void ShowMessage(string Msg)        {            this.listBox1.Items.Add(string.Format("The Closed port is  {0}", Msg));        }    }}
[解决办法]
volatile(C# 参考)
使用 Volatile 可以进行公有字段的同步锁操作。但是不会被编译器优化,而且不能用于局部变量。

所以,你可以声明一个 current 的类成员(不能是函数内部的局部变量),然后不需要lock来操作current 来进行计数了。

否则,就有如楼上的方法,使用 System.Threading.Interlocked.Increment(ref current) 的办法,进行自增的原子操作。

再有就是 lock 了,三者比较:

多CPU情况下,volatile最快,Interlocked 次之,Lock最慢!

因为 volatile 无需让CPU间相互通信并维护一直的高速缓存行,而是直接从内存中拿新的值,然后放回自己的寄存器。
一个mov eax,xx或者mov eax,[xx]即可。而 lock 其实要转为 interlocked ,还要进行临界区检查。

写法优雅不优雅不是重点,效率才重要,是吧。
[解决办法]
有了同步锁了,还没同步?
对current设置了同步锁,那么多线程在写这个字段的时候是排他的,所以,用了同步锁,就不需要你所说的同步了。这个和lock类似。
[解决办法]
探讨
23楼也没处理同步的问题啊

这么多回帖,好像除了我,都没处理同步的问题啊(27楼提了一下思路)

[解决办法]
探讨
试试这个

C# code
int volatile current = start;

[解决办法]
探讨
23楼也没处理同步的问题啊

这么多回帖,好像除了我,都没处理同步的问题啊(27楼提了一下思路)

[解决办法]
探讨
有了同步锁了,还没同步?
对current设置了同步锁,那么多线程在写这个字段的时候是排他的,所以,用了同步锁,就不需要你所说的同步了。这个和lock类似。

[解决办法]
转载自http://www.cnblogs.com/michaelxu/archive/2008/09/20/1293716.html
 一、volatile关键字

  volatile是最简单的一种同步方法,当然简单是要付出代价的。它只能在变量一级做同步,volatile的含义就是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我。(【转自www.bitsCN.com 】)因此,当多线程同时访问该变量时,都将直接操作主存,从本质上做到了变量共享。



  能够被标识为volatile的必须是以下几种类型:(摘自MSDN)

Any reference type.
Any pointer type (in an unsafe context).
The types sbyte, byte, short, ushort, int, uint, char, float, bool.
An enum type with an enum base type of byte, sbyte, short, ushort, int, or uint.
  如:

Code
public class A
{
private volatile int _i;
public int I
{
get { return _i; }
set { _i = value; }
}
}
  但volatile并不能实现真正的同步,因为它的操作级别只停留在变量级别,而不是原子级别。如果是在单处理器系统中,是没有任何问题的,变量在主存中没有机会被其他人修改,因为只有一个处理器,这就叫作processor Self-Consistency。但在多处理器系统中,可能就会有问题。 每个处理器都有自己的data cach,而且被更新的数据也不一定会立即写回到主存。所以可能会造成不同步,但这种情况很难发生,因为cach的读写速度相当快,flush的频率也相当高,只有在压力测试的时候才有可能发生,而且几率非常非常小。


[解决办法]

探讨
转载自http://www.cnblogs.com/michaelxu/archive/2008/09/20/1293716.html
 一、volatile关键字

  volatile是最简单的一种同步方法,当然简单是要付出代价的。它只能在变量一级做同步,volatile的含义就是告诉处理器, 不要将我放入工作内存, 请直接在主存操作我。


[解决办法]
楼主这样做有可能出现一些逻辑问题,或者用简单的做法:
比如扫描255个端口,用10个线程,那么就用第一个线程去扫描前25个,
依次类推,最后一个线程扫描剩下的端口.这样思路会明朗点.不会出现
交错现象.
[解决办法]
我是来学习的
[解决办法]
学习.......
[解决办法]
没关系~LZ,我也只是来学习的。。
[解决办法]
果然是个棘手的问题。。~
[解决办法]
我再描述下问题
用n个thread 同时分别做n件事情
然后 要求各个thread 做的事情不重复,而且总共要完成n件事情
[解决办法]
沙发

[解决办法]
来学习的。
[解决办法]
C# code
private void Scan(int threadCount, int startPort, int endPort)        {            Thread th;            TcpClient tc;            int port = startPort - 1;            for (int i = 0; i < threadCount; i++)            {                th = new Thread(new ThreadStart(delegate()                {                    while (port < endPort)                    {                        int testPort = Interlocked.Increment(ref port);                        string msg = " UnUsed";                        try                        {                            tc = new TcpClient();                            tc.Connect("localhost", testPort);                        }                        catch                        {                            msg = " Used";                        }                        BeginInvoke(new MethodInvoker(delegate()                        {                            listBox1.Items.Add(testPort.ToString() + msg);                        }));                        Thread.Sleep(1);                    }                }));                th.Start();            }        }
[解决办法]
只有增加端口的时候才需要同步,检测的时候就没必要了
[解决办法]
顶.................................
[解决办法]
47L 正解~经过测试了~
[解决办法]
有这么复杂嘛?


试试下面的代码

临界区同步线程

C# code
using System.Net.Sockets;using System.Threading;        void Scan(int count, int start, int end)        {            int current = start;            for (int i = 0; i < count; i++)            {                //我习惯使用闭包,也可以用带参数的委托,或者字段来共享数据                Thread th = new Thread(() =>                    {                       // lock (this)  //这样同步不对,失去了多线程的意义了                       // {                         int curtmp = 0;                         lock(this)                         {                                curtmp = current++;                          }                            while (curtmp <= end)                            {                                try                                {                                    TcpClient tc = new TcpClient();                                    tc.Connect("localhost", curtmp);                                    //已经在窗体装入时:Control.CheckForIllegalCrossThreadCalls = false;                                    //如果不设置这个属性,怎么才能把数据显示在列表框呢?                                    listBox1.Items.Add(curtmp);                                }                                catch { }                                lock(this)                                {                                    curtmp = current++;                                }                            }                       // }                    });                th.IsBackground = true;                th.Start();            }
[解决办法]
void Scan(int count, int start, int end)
{
int current = start;
for (int i = 0; i < count; i++)
{
//我习惯使用闭包,也可以用带参数的委托,或者字段来共享数据
Thread th = new Thread(() =>
{
while (cur<end)
{
int cur;
Interlocked.increment(ref cur);///加这个变量的原子操作 try
{
TcpClient tc = new TcpClient();
tc.Connect("jmc", cur);
//已经在窗体装入时:Control.CheckForIllegalCrossThreadCalls = false;
//如果不设置这个属性,怎么才能把数据显示在列表框呢?
listBox1.Items.Add(cur);
}
catch { }
}
});
th.IsBackground = true;
th.Start();
}

[解决办法]
///源代码出处:http://showjim.qsh.eu/
using System;
using System.Threading;
using System.Collections.Generic;

namespace showjim.sys.threading
{
/// <summary>
/// 并发线程队列
/// </summary>
public class concurrentQueue
{
/// <summary>
/// 异常模式并发阻塞检测时间
/// </summary>
private const int catchSleepTime = 60000;
/// <summary>
/// 默认并发阻塞检测时间
/// </summary>
private const int defaultSleepTime = 100;
/// <summary>
/// 阻塞检测是否睡眠模式,否则为异常模式
/// </summary>
private bool isSleep;
/// <summary>
/// 最大并发操作数
/// </summary>
private int maxCount;
/// <summary>
/// 并发阻塞检测时间
/// </summary>
private int sleepTime;
/// <summary>
/// 当前并发操作数
/// </summary>
private int currentCount = -1;
/// <summary>
/// 并发计数操作锁


/// </summary>
private object countLock = new object();
/// <summary>
/// 异常模式下当前阻塞检测线程
/// </summary>
private Thread waitThread = null;
/// <summary>
/// 异常模式阻塞检测线程锁
/// </summary>
private object waitLock = new object();

#region 初始化线程队列
/// <summary>
/// 初始化线程队列(异常模式阻塞检测)
/// </summary>
public concurrentQueue() : this(1, catchSleepTime, false) { }
/// <summary>
/// 初始化线程队列
/// </summary>
/// <param name="isSleep">阻塞检测是否睡眠模式,否则为异常模式</param>
public concurrentQueue(bool sleepOrCatch) : this(1, sleepOrCatch ? defaultSleepTime : catchSleepTime, sleepOrCatch) { }
/// <summary>
/// 初始化线程队列(异常模式阻塞检测)
/// </summary>
/// <param name="count">最大并发操作数</param>
public concurrentQueue(int count) : this(count, catchSleepTime, false) { }
/// <summary>
/// 初始化线程队列(异常模式阻塞检测)
/// </summary>
/// <param name="count">最大并发操作数</param>
/// <param name="sleep">并发阻塞检测时间</param>
public concurrentQueue(int count, int sleep) : this(count, sleep, false) { }
/// <summary>
/// 初始化线程队列
/// </summary>
/// <param name="count">最大并发操作数</param>
/// <param name="isSleep">阻塞检测是否睡眠模式,否则为异常模式</param>
public concurrentQueue(int count, bool sleepOrCatch) : this(count, sleepOrCatch ? defaultSleepTime : catchSleepTime, sleepOrCatch) { }
/// <summary>
/// 初始化线程队列
/// </summary>
/// <param name="count">最大并发操作数</param>
/// <param name="sleep">并发阻塞检测时间</param>
/// <param name="isSleep">阻塞检测是否睡眠模式,否则为异常模式</param>
public concurrentQueue(int count, int sleep, bool sleepOrCatch)
{
isSleep = sleepOrCatch;
maxCount = (count < 1 ? 1 : count);
sleepTime = (sleep < 1 ? (isSleep ? defaultSleepTime : catchSleepTime) : sleep);
}
#endregion

#region 并发操作申请
/// <summary>
/// 并发操作申请
/// </summary>
public void enter()
{
Monitor.Enter(countLock);
try
{
if ((++currentCount) == maxCount)
{
if (isSleep)
{
while (currentCount == maxCount) Thread.Sleep(sleepTime);
}
else
{
try
{
Monitor.Enter(waitLock);
waitThread = Thread.CurrentThread;
Monitor.Exit(waitLock);
while (currentCount == maxCount) Thread.Sleep(sleepTime);
}
catch { }
}
}
}
finally { Monitor.Exit(countLock); }
}
#endregion

#region 尝试并发操作申请
/// <summary>
/// 尝试并发操作申请
/// </summary>
/// <returns>申请是否成功</returns>
public bool tryEnter()
{
bool isEnter = false;
Monitor.Enter(countLock);
try
{
if (isEnter = (currentCount < maxCount - 1)) currentCount++;
}
finally { Monitor.Exit(countLock); }


return isEnter;
}
/// <summary>
/// 尝试并发操作申请
/// </summary>
/// <param name="maxSleepTime">最长等待时间</param>
/// <returns>申请是否成功</returns>
public bool tryEnter(int maxSleepTime)
{
bool isEnter = true;
if (maxSleepTime < 0) isEnter = tryEnter();
else
{
Monitor.Enter(countLock);
try
{
if ((++currentCount) == maxCount)
{
if (isSleep)
{
DateTime exitTime = DateTime.Now.AddMilliseconds(maxSleepTime);
for (maxSleepTime = (int)(new TimeSpan(exitTime.Ticks - DateTime.Now.Ticks).TotalMilliseconds); maxSleepTime > 0 && currentCount == maxCount; maxSleepTime = (int)(new TimeSpan(exitTime.Ticks - DateTime.Now.Ticks).TotalMilliseconds)) Thread.Sleep(maxSleepTime > sleepTime ? sleepTime : maxSleepTime);
}
else
{
try
{
Monitor.Enter(waitLock);
waitThread = Thread.CurrentThread;
Monitor.Exit(waitLock);
Thread.Sleep(maxSleepTime);
}
catch { }
}
if (!(isEnter = (currentCount != maxCount))) currentCount--;
}
}
finally { Monitor.Exit(countLock); }
}
return isEnter;
}
#endregion

#region 并发操作结束解锁
/// <summary>
/// 并发操作结束解锁
/// </summary>
public void exit()
{
currentCount--;
if (!isSleep)
{
Monitor.Enter(waitLock);
Thread wait = waitThread;
waitThread = null;
Monitor.Exit(waitLock);
if (wait != null) wait.Interrupt();
}
}
#endregion
}
}

[解决办法]
定义并发线程队列
private static concurrentQueue queue = new concurrentQueue(10);
调用方式
queue.enter();
try
{
//do...
}
finally{queue.exit();}
[解决办法]
经典贴~
[解决办法]
做端口扫描怎么能用同步呢?
影响速度
[解决办法]
47楼的测试通过,不过如果在稍慢过程中注销窗口的话会报错,修改后的代码如下:

C# code
        void Scan(int threadCount, int startPort, int endPort) {            Thread th;            TcpClient tc;            int port = startPort - 1;            for (int i = 0; i < threadCount; i++) {                th = new Thread(new ThreadStart(delegate() {                    while (port < endPort) {                        int testPort = Interlocked.Increment(ref port);                        string msg = " UnUsed";                        try {                            tc = new TcpClient();                            tc.Connect("localhost", testPort);                        }                        catch {                            msg = " Used";                        }                        BeginInvoke(new MethodInvoker(delegate() {                           [color=#FF0000] if (listBox1.IsHandleCreated)                            {                                listBox1.Items.Add(testPort.ToString() + msg);                            }[/color]                                                    }));                        //Thread.Sleep(1);                    }                }));                th.Start();            }        } 


[解决办法]
想加个颜色的,没想到没效果,再发一次

C# code
        void Scan(int threadCount, int startPort, int endPort) {            Thread th;            TcpClient tc;            int port = startPort - 1;            for (int i = 0; i < threadCount; i++) {                th = new Thread(new ThreadStart(delegate() {                    while (port < endPort) {                        int testPort = Interlocked.Increment(ref port);                        string msg = " UnUsed";                        try {                            tc = new TcpClient();                            tc.Connect("localhost", testPort);                        }                        catch {                            msg = " Used";                        }                        BeginInvoke(new MethodInvoker(delegate() {                            if (listBox1.IsHandleCreated)                            {                                listBox1.Items.Add(testPort.ToString() + msg);                            }                                                    }));                        //Thread.Sleep(1);                    }                }));                th.Start();            }        }
[解决办法]
ls的testPort正确?
[解决办法]
注销窗口的话会报错 是因为线程没关闭~
[解决办法]
探讨
C# code
private void Scan(int threadCount, int startPort, int endPort)
{
Thread th;
TcpClient tc;
int port = startPort - 1;
for (int i = 0; i < threadCount; i++)
{
th = new Thread(new ThreadStart(delegate()
{
while (port < endPort)
{


[解决办法]
我想了个笨办法,将扫描的端口数量按照线程数进行分块,一个线程扫一个块,这样就不存在出错了噻.
[解决办法]
路过
[解决办法]
[align=center]顶一下[align]
[解决办法]
hehe dou 大家好啊

[解决办法]
路过 看看
[解决办法]
来学习学习
[解决办法]
学习学习,呵呵
[解决办法]
进来学习学习。
[解决办法]
mark!
[解决办法]
mark
[解决办法]
谢谢楼主分享
[解决办法]
ding
[解决办法]
显然,在这里,真正的资源是端口,不应该对任何一个端口进行同步访问。
所以,开启多个线程对同一个端口列表进行扫描没有意义。
正确的做法是将要使用资源分成几部分,对各部分使用不同的线程进行并行处理。
换到这里,就是把要扫描的端口列表分为几部分,开启多个线程,每个线程扫描其中的一部分。
[解决办法]
把所有端口放在 queue 中,dequeue 时加个 mutex 进行同步控制,这样每个新线程从 queue 中拿一个端口进行扫描,扫描完成再从 queue 中 dequeue 一个,直到所有端口扫描完成,解决了端口扫描时间不等问题。


[解决办法]

进来学习学习....
[解决办法]
学习 .......
[解决办法]
抢分,来晚了
[解决办法]
UP
[解决办法]
Mark!
[解决办法]
UP
[解决办法]
int volatile current = start;

[解决办法]
up
[解决办法]
学习了
[解决办法]
不错。
[解决办法]
线程问题要顶起!
[解决办法]

[解决办法]
代码不写全没办法看啊

[解决办法]

[解决办法]
up....
[解决办法]
只看了第一个楼,后面没仔细看,觉得这个想法有个问题. 起很多thread其实影响performance的,你的计算机有多少个core? 如果传入count = 100,不可能有100个thread同时在跑,除非你有非常powerful的机器。所以正确的做法是thread pool + APM.

读书人网 >C#

热点推荐