分类目录归档:C#

C#按字节截取字符串

一行包含汉字、字母、数字的文本,如:string txt = “一段C#代码值123元,你能接收吗?”; 如果我想把数字123截出来,直接使用txt.substring(12,3),实际截出的是“你能接”。所以可以考虑先转化为字节后再截取,代码如下:
[csharp]
public class StringUtil
{
static string SubstringByte(string txt, int start, int length, string charset)
{
Encoding enc = Encoding.GetEncoding(charset);
byte[] bytes = enc.GetBytes(txt);

return enc.GetString(bytes, start, length);
}
}
[/csharp]

C#实现的HttpSQS客户端封装类

[csharp]
class HttpSQSClient
{
private String server, port, charset;

public HttpSQSClient(String server, String port, String charset)
{
this.server = server;
this.port = port;
this.charset = charset;
}

private string DoProcess(String urlstr)
{
string result = String.Empty;

Uri url = null;
try
{
url = new Uri(urlstr);
}
catch (Exception e)
{
return "The httpsqs server must be error";
}

try
{
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "get";

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
System.Text.Encoding encode;
try
{
encode = System.Text.Encoding.GetEncoding(response.CharacterSet);
}
catch
{
encode = System.Text.Encoding.Default;
}

System.IO.Stream stream = response.GetResponseStream();
System.IO.StreamReader read = new System.IO.StreamReader(stream, encode);
result = read.ReadToEnd();

response.Close();

return result;
}
catch (IOException ex)
{
return "Get data error";
}
}

public String MaxQueue(String queue_name, String num)
{
String urlstr = "http://" + this.server + ":" + this.port + "/?name="
+ queue_name + "&opt=maxqueue&num=" + num;

String result = null;

result = this.DoProcess(urlstr);
return result;
}

public String Reset(String queue_name)
{
String urlstr = "http://" + this.server + ":" + this.port + "/?name="
+ queue_name + "&opt=reset";
String result = null;

result = this.DoProcess(urlstr);
return result;
}

public String View(String queue_name, String pos)
{
String urlstr = "http://" + this.server + ":" + this.port
+ "/?charset=" + this.charset + "&name=" + queue_name
+ "&opt=view&pos=" + pos;
String result = null;

result = this.DoProcess(urlstr);
return result;
}

public String Status(String queue_name)
{
String urlstr = "http://" + this.server + ":" + this.port + "/?name="
+ queue_name + "&opt=status";
String result = null;

result = this.DoProcess(urlstr);
return result;
}

public String Get(String queue_name)
{
String urlstr = "http://" + this.server + ":" + this.port
+ "/?charset=" + this.charset + "&name=" + queue_name
+ "&opt=get";
String result = null;

result = this.DoProcess(urlstr);
return result;
}

public String Put(String queue_name, String data)
{
String ret = String.Empty;
String urlstr = "http://" + this.server + ":" + this.port + "/?name="
+ queue_name + "&opt=put";
Uri url = null;
try
{
url = new Uri(urlstr);
}
catch (Exception)
{
return "The httpsqs server must be error";
}

HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url);
request.Method = "post";
byte[] requestBytes = System.Text.Encoding.UTF8.GetBytes(data);
request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = requestBytes.Length;
request.Timeout = 6000;
try
{
Stream requestStream = request.GetRequestStream();
requestStream.Write(requestBytes, 0, requestBytes.Length);
requestStream.Close();

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
StreamReader reader = new StreamReader(response.GetResponseStream(), System.Text.Encoding.Default);
ret = reader.ReadToEnd();
}
catch (Exception)
{
return "Put data error";
}

return ret;
}
}
[/csharp]

除了put方法使用post方式请求外,其他方法都用post方式。

c#读写rabbitmq

我在一台centos机器上装了rabbitmq,因为历史原因,需要用多种语言来访问,包括:java,c#,php等。
1.首先在服务器上建立一测试帐号,添加测试vhost
[bash]
/usr/sbin/rabbitmqctl add_user test_user test_pass
/usr/sbin/rabbitmqctl add_vhost vhost_test
/usr/sbin/rabbitmqctl set_permissions -p vhost_test test_user ‘.*’ ‘.*’ ‘.*’
[/bash]

2.然后创建一个生产方法
[csharp]
public static void writeKeyword(string message)
{
string exchange = "exchange_test"; //
string routingKey = "routingkey_test";
string queueName = "queue_test";
ConnectionFactory cf = new ConnectionFactory();
cf.Uri = ConfigurationManager.AppSettings.Get("MQ_URI"); //类似amqp://test_user:test_pass@localhost:5672/vhost_test

using (IConnection conn = cf.CreateConnection())
{
using (IModel ch = conn.CreateModel())
{

if (exchange != "")
{
ch.ExchangeDeclare(exchange, ExchangeType.Direct);
ch.QueueDeclare(queueName, false, false, false, null);
ch.QueueBind(queueName, exchange, routingKey, null);
}
ch.BasicPublish(exchange,
routingKey,
null,
Encoding.UTF8.GetBytes(message));

//ch.BasicPublish("", queueName, null, Encoding.Default.GetBytes(message));
}
}
}
[/csharp]

3.再创建一个消费方法
[csharp]
public Keyword getKeyword()
{
Keyword keyword = null;
log.Debug(queueName);
using (IModel ch = conn.CreateModel())
{
conn.AutoClose = true;

ch.QueueDeclare(queueName, false, false, false, null);
BasicGetResult result = ch.BasicGet(queueName, false);
if (result == null)
{
Console.WriteLine("No message available.");
}
else
{
log.Debug("content: "+Encoding.Default.GetString(result.Body));

//ch.BasicAck(result.DeliveryTag, false);
//Console.WriteLine("Message:");
//DebugUtil.DumpProperties(result, Console.Out, 0);

keyword = new Keyword();
keyword.keyword = Encoding.Default.GetString(result.Body);

}

}
return keyword;
}
[/csharp]

关于c#中类库的扩展方法的使用

今天遇到一奇怪的问题,先看代码.

[csharp]
Dictionary<string,string> values = new Dictionary<string,string> ();
values.Add("网址", url);
values.Add("时间", DateTime.Now.ToString());
MessageBox.Show("第一个值:"+values.First().Value);
[/csharp]

同样的一段构造Dictionary的代码,在winform程序里可以用First()函数,但在类库里却不能用,很奇怪。查了一下msdn,发现这个方法是扩展方法,非基本方法,猜想可能得依赖其他的库才能运行,比较了一下using,发现少了一个

[csharp]
using System.Linq;
[/csharp]

加上后果然正确。

java调用.net webservice的完整实例

Java客户端调用Web Service的一般有以下三种方式:
生成的stub、proxy(动态代理)以及dispatch(动态调用接口)。dispatch又分为payload和message两种方式。
这个实例仅就dispatch的message方式进行介绍。

C#代码
[csharp]
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;
using System.Web.Services.Description;

namespace WebService1
{
/// <summary>
/// Service1 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
[SoapDocumentService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)]
public class Service1 : System.Web.Services.WebService
{

[WebMethod]
public string HelloWorld(string strHost)
{
return "Hello World, "+strHost;
}
}
}
[/csharp]

Java调用程序
[java]
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.soap.MessageFactory;
import javax.xml.soap.SOAPBody;
import javax.xml.soap.SOAPBodyElement;
import javax.xml.soap.SOAPElement;
import javax.xml.soap.SOAPMessage;
import javax.xml.ws.BindingProvider;
import javax.xml.ws.Dispatch;
import javax.xml.ws.Service;
import javax.xml.ws.WebServiceException;
import javax.xml.ws.soap.SOAPBinding;

public class WebServiceTest {

/**
* @param args
*/
public static final String targetNamespace = "http://tempuri.org/";
//服务名
public static final String serName = "Service1";
//端口名
public static final String pName = "5756";
//服务地址
public static final String endpointAddress = "http://localhost:5756/Service1.asmx?wsdl";
//方法名
public static final String OPER_NAME = "HelloWorld";
//参数名
public static final String INPUT_NMAE = "strHost";

public static void main(String[] args) throws Exception {
QName serviceName = new QName(targetNamespace, serName);
QName portName = new QName(targetNamespace, pName);

javax.xml.ws.Service service = Service.create(serviceName);
service.addPort(portName, SOAPBinding.SOAP11HTTP_BINDING, endpointAddress);

Dispatch<SOAPMessage> dispatch = service.createDispatch(portName,
SOAPMessage.class, Service.Mode.MESSAGE);

BindingProvider bp = (BindingProvider) dispatch;
Map<String, Object> rc = bp.getRequestContext();
rc.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
rc.put(BindingProvider.SOAPACTION_URI_PROPERTY, OPER_NAME);
MessageFactory factory = ((SOAPBinding)bp.getBinding()).getMessageFactory();

SOAPMessage request = factory.createMessage();
SOAPBody body = request.getSOAPBody();
QName payloadName = new QName(targetNamespace, OPER_NAME);
SOAPBodyElement payload = body.addBodyElement(payloadName);

SOAPElement message = payload.addChildElement(INPUT_NMAE);
message.addTextNode("xyz");
SOAPMessage reply = null;

try
{
reply = dispatch.invoke(request);
}
catch (WebServiceException wse)
{
wse.printStackTrace();
}
SOAPBody soapBody = reply.getSOAPBody();
SOAPBodyElement nextSoapBodyElement = (SOAPBodyElement)soapBody.getChildElements().next ();
SOAPElement soapElement = (SOAPElement)nextSoapBodyElement.getChildElements().next();

System.out.println("获取回应信息为:" + soapElement.getValue());
}
}
[/java]

java调用c#写的webservice,服务器未能识别 HTTP 头 SOAPAction 的值[转]

今天用CXF去调用.net写的一个webservice服务报错,网上搜个解决办法,做个记录

服务器未能识别 HTTP 头 SOAPAction 的值 - 小玩子 - 世界任我行!

解决办法:服务器未能识别 HTTP 标头 SOAPAction 的值

本文主要探讨跨平台调用 Web Service 出现: ” 服务器未能识别 HTTP 标头 SOAPAction 的值 ” 的解决办法。

症状一:

Web Service + ASP.NET 应用程序部署到服务器默认目录中,在 IE 中用 http://< 服务器地址 >/< 程序目录名 >/< 默认启动页面名 > 发 生 “ 服务器未能识别 HTTP 标头 SOAPAction 的值 ” 错误。

症状二:

在 Java 平台上调用 .NET Web Service 的服务时,出现 ” 服务器未能识别 HTTP 标头 SOAPAction 的值 ” 。

症状三:

在 Java 平台下调用 .NET WEB Service ,出现数据时有时无。

解决对策:

给 .NET 的 WebService 类(即 .asmx 文件下的类)添加属性[SoapDocumentService(RoutingStyle=SoapServiceRoutingStyle.RequestElement)]

以下是NET代码,

using System;
using System.Collections;
using System.ComponentModel;
using System.Data;
using System.Web;
using System.Web.Services;
using System.Web.Services.Protocols;

namespace WebService
{
/// <summary>
/// Service1 的摘要说明
/// </summary>
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
// 若要允许使用 ASP.NET AJAX 从脚本中调用此 Web 服务,请取消对下行的注释。
// [System.Web.Script.Services.ScriptService]
  [SoapDocumentService(RoutingStyle = SoapServiceRoutingStyle.RequestElement)] 
public class Service1 : System.Web.Services.WebService
{

[WebMethod]
public string HelloWorld()
{
return “Hello World”;
}
[WebMethod]
public USER GetObj()
{
USER user = new USER();
user.Name = “习明凡”;
user.Pass = “123456″;
return user;
}
}
}

小知识:

什么是 SoapAction ?它在 WSDL 中有何作用?

SOAPAction HTTP request header 被用来标识 SOAP HTTP 请求的目的地,其值是个 URI 地址。 SOAP 发送并不限制格式、 URI 特征或其必须可解析,那么在这种情况下,发送一个 HTTP SOAP 请求时,其 HTTP 客户端必须使用 / 指明 SOAPAction HTTP request header 。

SOAPAction header 的内容可以被用在服务端,诸如:防火墙适当的过滤基于 HTTP 的 SOAP 请求消息等场景。 SOAPAction header 的值为空串 (“”) 表示 SOAP 消息的目的地由 HTTP 请求的 URI 标识;无值则表示没有指定这条消息的目的地。

java代码:
import org.apache.cxf.jaxws.JaxWsProxyFactoryBean;
import org.tempuri.Service1Soap;
import org.tempuri.USER;

public class Test {

public static void main(String[] args) {

JaxWsProxyFactoryBean soapFactoryBean = new JaxWsProxyFactoryBean();
soapFactoryBean.setAddress(“http://10.8.0.143/webservice/Service1.asmx“);
soapFactoryBean.setServiceClass(Service1Soap.class);
Object o = soapFactoryBean.create();
Service1Soap soap = (Service1Soap)o;
System.out.println(soap.helloWorld());

USER user = soap.getObj();
System.out.println(user.getName());
}
}

分享如何用C# Button实现下拉菜单[转]

本文为你讲解了C# Button下拉菜单实现的思路,步骤及代码!笔者讲述的很清楚,很有条理,实用性很强的。主要的思路还是在于要把ContextMenuStrip控件实例与按钮关联,并取消按钮的右击事件。

C# Button实现下拉菜单为实现这个功能, 花费的时间太长了, 觉得本人真够笨. 回过头来看, 其实很简单的东西!

在项目中,要用到按钮实现下拉菜单的功能,而且是在MDI窗体中。当菜单的显示范畴超出MDI窗体的工做区时,就要换另一显示方式,不至于显示混乱。如图:

实现C# Button下拉菜单
实现C# Button下拉菜单

实现C# Button下拉菜单
实现C# Button下拉菜单

(发觉一问题,如果把Form1拉到像Form3的大小,还会出现图一的情况。客户没这么邪吧)

C# Button下拉菜单实现思路:

1、要把ContextMenuStrip控件实例与按钮关联

2、取得MDI工做区的大小

3、取消按钮的右击事件(因为与ContextMenuStrip相关系的控件右键都会响应且显示)

4、鼠标单击时设置菜单显示位置

C# Button下拉菜单实现步骤:

1、创建用户控件,且用户控件承继自Button类

2、定义ContextMenuStrip对象

3、定义显示ContextMenuStrip对象立标point

4、重写按钮单击事件和ContextMenuStrip属性(设置与之关联的ContextMenuStrip实例用到),还有重写鼠标右击事件,使其不响应任何操做

C# Button下拉菜单代码:

[csharp]
///

/// 说明: 使用此Button时要设置ContextMenuStrip属性值
/// 单击些Button的Click事件要传入所在工做区的宽高
/// 如果没有所需的属性值,则如平时所使用的Button一至
/// 使用例子:
/// DropButton.WorkSizeX =
this.MdiParent.ClientRectangle.Width;
/// DropButton.WorkSizeY =
this.MdiParent.ClientRectangle.Height;
/// 应用:
/// 创建人: lrj
/// 创建日期:2008-05-22
/// 修改人:
/// 修改日期:
///

public partial class DropButton : Button
{
private ContextMenuStrip contextMenuStrip;
private Point point; //立标
private int x = 0; //立标x
private int y = 0; //立标y
private int workSize_x;//工做区x
private int workSize_y;//工做区y
public DropButton()
{
InitializeComponent();
x = this.Size.Width ;
y = 0;
}
///

/// 工做区的完
///

public int WorkSizeX
{
get { return workSize_x; }
set { workSize_x = value; }
}
///

/// 工做区的高
///

public int WorkSizeY
{
get { return workSize_y; }
set { workSize_y = value – 55; }
}
///

/// ContextMenuStrip菜单
///

public override ContextMenuStrip ContextMenuStrip
{
get { return contextMenuStrip; }
set
{
if (contextMenuStrip != null)
{
contextMenuStrip = value;
}
}
}
//
//重写的单击事件
//
protected override void OnClick(EventArgs e)
{
base.OnClick(e);
//菜单在工做区离边框的宽高
int _x = this.Parent.Location.X + this.Location.X +
this.Size.Width + contextMenuStrip.Size.Width;
int _y = this.Parent.Location.Y + this.Location.Y +
contextMenuStrip.Size.Height ;
if
(_x < WorkSizeX – 8)
{
x = this.Size.Width;
}
else
{
x = 0 – contextMenuStrip.Size.Width;
}
if
(_y < WorkSizeY)
{
y = 0;
}
else
{
y = 0 – contextMenuStrip.Size.Height + this.Size.Height;
}
point =
new Point(x, y);
contextMenuStrip.Show(this, point);
}
//
//使鼠标右键失效
//
protected override void OnMouseDown(MouseEventArgs mevent)
{
base.OnMouseDown(mevent);
if (mevent.Button.ToString() != "Right")
{
}
}
}
[/csharp]

以上讲述了实现C# Button下拉菜单的思路、步骤及代码,希望能给大家带来帮助。
摘自: http://developer.51cto.com/art/200909/151112.htm

c#实现抓取imei码信息,手工输入验证码

从一网站抓取imei信息,有验证码,而且模拟起来比较费劲,于是就直接用webbrowser算了。
直接上代码吧。
[csharp]
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.IO;

namespace ShowSearchPage
{
public partial class Form1 : Form
{
private String imgUrl;
string url = "http://www.xyz.com/abc.aspx";
private WebBrowser wb = new WebBrowser();
Uri baseUri;
WebClient wc = new WebClient();

public Form1()
{
InitializeComponent();
}

private void button1_Click(object sender, EventArgs e)
{
wb.Navigate(url);
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
}
public static Image BytesToImage(byte[] bytes)
{
MemoryStream ms = new MemoryStream(bytes);
Image img = Image.FromStream(ms);
return img;
}

private void webBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
if (wb.Document.Url == e.Url)
{
//加载完毕。
HtmlAgilityPack.HtmlDocument html = new HtmlAgilityPack.HtmlDocument();
html.LoadHtml(wb.DocumentText); //.ToString()
HtmlAgilityPack.HtmlNode htmlNode = html.DocumentNode;
HtmlAgilityPack.HtmlNode tagImg = htmlNode.SelectSingleNode("//*[@id=\"SNTD\"]/img");
if (tagImg != null)
{
string imgReUri = tagImg.GetAttributeValue("src","");
baseUri = new Uri(url);
Uri imgUri = new Uri(baseUri, imgReUri);

byte[] imgData = wc.DownloadData(imgUri);

pictureBox1.Image = BytesToImage(imgData);
}
}
if (wb.Document.Url.ToString().Contains("Check/IMEIValidateDetail.aspx?a="))
{
//内容
HtmlAgilityPack.HtmlDocument html = new HtmlAgilityPack.HtmlDocument();
html.LoadHtml(wb.DocumentText);
HtmlAgilityPack.HtmlNode htmlNode = html.DocumentNode;
HtmlAgilityPack.HtmlNode summary = htmlNode.SelectSingleNode("//table[@class=\"checkContent2\"]");
if (summary != null)
{
//webBrowser1.DocumentText = summary.InnerText;
richTextBox1.Text = summary.InnerHtml;
}

//图片
HtmlAgilityPack.HtmlNode iframe = htmlNode.SelectSingleNode("//table[@class=\"checkContent2\"]/tr[1]/td[1]/iframe");
if (iframe != null)
{
string frameRes = iframe.GetAttributeValue("src", "无图片");
Uri frameUri = new Uri(baseUri, frameRes);
string iframePageData = wc.DownloadString(frameUri);
html.LoadHtml(iframePageData);
htmlNode = html.DocumentNode;
HtmlAgilityPack.HtmlNode imgNode = htmlNode.SelectSingleNode("//*[@id=\"imgEQ\"]");
if (imgNode != null)
{
string thumbRes = imgNode.GetAttributeValue("src", "");
Uri thumbUri = new Uri(baseUri, thumbRes);
pictureBox2.Load(thumbUri.ToString());
}

}
}
}

private void button2_Click(object sender, EventArgs e)
{
wb.Document.GetElementById("ctl00$ContentPlaceHolder1$IMEICode").InnerText = "12345678904535";
wb.Document.GetElementById("ctl00_ContentPlaceHolder1_txtValidateCode").InnerText = textBox1.Text;
wb.Document.GetElementById("ctl00_ContentPlaceHolder1_submit").InvokeMember("click");
while (wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
}

private void Form1_Load(object sender, EventArgs e)
{
wb.Navigate(url);
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(webBrowser_DocumentCompleted);
}

private void button3_Click(object sender, EventArgs e)
{
foreach (HtmlElement he in wb.Document.GetElementsByTagName("a"))
{
if ("(查看详细)".Equals(he.InnerText.Trim()))
{
he.InvokeMember("click");
break;
}
}
}
}
}

[/csharp]
抓取imei码效果图

一种减少mongodb压力的交互设计方法

有一个按关键词采集数据的分布式程序用到了mongodb,各个客户端用findAndModify命令每次从服务端的mongodb中读取一条记录,执行完后再更新到库里。
[csharp]
public static Keyword Get()
{
Keyword keyword = null;
bool notGot = true;
int retries = 0;
while (notGot && retries < 3)
{
try
{
if (collection == null)
collection = db.GetCollection<Keyword>("keyword");

var query = Query.And(
Query.GTE("queries", Properties.Settings.Default.MinQueries),
Query.LTE("queries", Properties.Settings.Default.MaxQueries),
Query.Or(Query.Exists("flag", false), Query.EQ("flag", 0))
);
var update = Update.Set("flag", -1);
var result = collection.FindAndModify(
query,
null,
update,
true // return new document
);
if (result != null)
{
BsonDocument doc = result.ModifiedDocument;
if (doc != null)
{
keyword = new Keyword();
keyword.keyword = doc["keyword"].AsString.Trim().Replace("’", "").Replace("\\","") ;
//if (keyword.keyword.Contains("’")||keyword.keyword.Contains("\\")) continue;
//if(doc["queries"].GetType().Equals(System.Type.))
double qq = Convert.ToDouble(doc["queries"]);
keyword.queries = Convert.ToInt32(Math.Floor(qq));
notGot = false;
}
else
{
retries++;
}
}

//MessageBox.Show(keyword.keyword + " – " + keyword.queries);
}
catch (MongoConnectionException mce)
{
retries = 0;
log.Error("MongoDB连接出现问题,程序将会一直每隔5秒重试一次,直到连接正常为止。");
Thread.Sleep(5000);
Reconnect();
}
catch (Exception ext)
{
log.Error("【获取关键词时错误】"+ext.Message+" – "+ext.GetType());
if (ext.InnerException == null)
{
log.Error(ext.StackTrace);
}
else
{
log.Error(ext.InnerException.StackTrace);
}
Thread.Sleep(5000);
//BsonDocument log = new BsonDocument {
// { "client", Properties.Settings.Default.Client },
// { "time", string.Format("{0:yyyy-MM-dd HH:mm:ss}",DateTime.Now) },
// { "description", "found error while getting keyword: "+e.Message}
//};
//db = server.GetDatabase(Properties.Settings.Default.DbName);
retries++;
log.Error("已经重试次数:"+retries);
Reconnect();
}
}
return keyword;
}
[/csharp]
flag的初始状态为0或没有初始状态,取完一条以后会把flag标识置为-1,当保存更新的时候再给状态改为1,一轮结束后再把此范围内的所有记录的flag都置为0.
但这样读写比较频繁,会给mongodb造成比较大的压力,而且会出现类似下面的锁的问题:
[conn463] warning: ClientCursor::yield can’t unlock b/c of recursive lock ns:
现在改批量取,实时更新的办法,代码如下:
[csharp]
public static List<Keyword> Select(int skip, int limit)
{
List<Keyword> keywords = null; // new List<Keyword>();
bool notSelected = true;
int retries = 0;
while (notSelected && retries < 3)
{
try
{
MongoCollection<BsonDocument> collKeyword = db.GetCollection<BsonDocument>("keyword");
var query = Query.And(
Query.GTE("queries", Properties.Settings.Default.MinQueries),
Query.LTE("queries", Properties.Settings.Default.MaxQueries),
Query.Or(Query.Exists("flag", false), Query.EQ("flag", 0))
);

if (limit == 0)
{
var cursor = collKeyword.Find(query).SetSkip(skip);
if (cursor != null)
{
keywords = new List<Keyword>();
//keywords = cursor.ToList();
foreach (BsonDocument keyword in cursor)
{
Keyword k = new Keyword();
k.keyword = keyword.GetValue("keyword").ToString();
k.queries = Convert.ToInt32(keyword.GetValue("queries"));
keywords.Add(k);
}
notSelected = false;
}
}
else
{
var cursor = collKeyword.Find(query).SetSkip(skip).SetLimit(limit);
if (cursor != null)
{
keywords = new List<Keyword>();
//keywords = cursor.ToList();
foreach (BsonDocument keyword in cursor)
{
Keyword k = new Keyword();
k.keyword = keyword.GetValue("keyword").ToString();
k.queries = Convert.ToInt32(keyword.GetValue("queries"));
keywords.Add(k);
}
notSelected = false;
}
}

notSelected = false;
}
catch (Exception e)
{
Thread.Sleep(3000);
retries++;
Reconnect();
}
}

return keywords;
}
[/csharp]
这样即使程序断掉,再启动时也可以从下一条开始,不至于重复抓取。