csharp Задачадлямногопотокасблокировкойтаблиц

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了csharp Задачадлямногопотокасблокировкойтаблиц相关的知识,希望对你有一定的参考价值。

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.IO;
using System.Text.RegularExpressions;
using ZennoLab.CommandCenter;
using ZennoLab.InterfacesLibrary;
using ZennoLab.InterfacesLibrary.ProjectModel;
using ZennoLab.InterfacesLibrary.ProjectModel.Collections;
using ZennoLab.InterfacesLibrary.ProjectModel.Enums;
using ZennoLab.Macros;
using Global.ZennoExtensions;
using ZennoLab.Emulation;

namespace ZennoLab.OwnCode
{
    /// <summary>
	/// A simple class of the common code
	/// </summary>
	public class CommonCode
	{
		/// <summary>
		/// Lock this object to mark part of code for single thread execution
		/// </summary>
		public static object SyncObject = new object();

		// Insert your code here
	}
}
//Данный сниппет предназначен для демонстрации многопоточной работы с БД (добавьте текущий проект в ZennoPoster и запустите в несколько потоков)

string strDBConnString = project.Variables["cfg_db_connstring"].Value;
int intMaxTasks = Convert.ToInt32(project.Variables["cfg_tasks_per_execution"].Value);
bool blnLockTables = Convert.ToBoolean(project.Variables["cfg_use_table_locks"].Value);

//добавляем несколько "заданий" в таблицу db_jobs (при штатной работе фермы эта информация появлялась бы в таблице в результате других процессов)
List<int> lstRandomProfiles = new List<int>() {1, 2, 3, 4, 5};
lstRandomProfiles.Shuffle();
string strAddTasksQuery = String.Format("INSERT INTO db_tasks (profile_id, task_type, post_text, post_image, object) VALUES ({0}, 'post', 'this is a texxt', 'image1.jpg', 'http://vk.com/supergruppa');" +
    "INSERT INTO db_tasks (profile_id, task_type, object) VALUES ({1}, 'like', 'https://vk.com/wall-2158488_268002');" +
	"INSERT INTO db_tasks (profile_id, task_type, object) VALUES ({2}, 'invite', 'https://vk.com/id139687748');" +
	"INSERT INTO db_tasks (profile_id, task_type, object) VALUES ({3}, 'like', 'https://vk.com/wall-2158488_636329');" +
	"INSERT INTO db_tasks (profile_id, task_type, post_text, post_image, object) VALUES ({4}, 'post', 'text namba tu', 'image2.jpg', 'http://vk.com/goodgruppa');", 
	lstRandomProfiles[0], lstRandomProfiles[1], lstRandomProfiles[2], lstRandomProfiles[3], lstRandomProfiles[4]);
ZennoPoster.Db.ExecuteNonQuery(strAddTasksQuery, null, ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient, strDBConnString);

//получаем свободный профиль (со статусом ready), для которого количество "заданий" больше нуля ("нативная" работа с MySqlClient)
var ProfileSelectCommand = new MySql.Data.MySqlClient.MySqlCommand();
try{
	ProfileSelectCommand.Connection = new MySql.Data.MySqlClient.MySqlConnection(strDBConnString);
}catch(Exception e){
	return "MySql connect failed";
}
ProfileSelectCommand.Connection.Open();

//блокируем таблицу db_profiles для записи другими потоками
string strLockQuery = "LOCK TABLES db_profiles WRITE, db_tasks READ";
MySql.Data.MySqlClient.MySqlCommand NonQueryDBCommand = new MySql.Data.MySqlClient.MySqlCommand(strLockQuery, ProfileSelectCommand.Connection);
if (blnLockTables) NonQueryDBCommand.ExecuteNonQuery();

string strSelectProfileQuery = "SELECT db_profiles.id, login, password, db_profiles.status " +
	"FROM db_profiles LEFT JOIN db_tasks ON db_profiles.id = db_tasks.profile_id " +
	"WHERE db_tasks.status='wait' " +
	"GROUP BY login, password, db_profiles.status " +
	"HAVING db_profiles.status='ready' AND COUNT(task_type)>0 " +
	"ORDER BY COUNT(db_tasks.task_type) DESC LIMIT 1;";
ProfileSelectCommand.CommandText=strSelectProfileQuery;
var ProfileLoadReader = ProfileSelectCommand.ExecuteReader();

string strCurrProfileID=String.Empty;
string strLogin = String.Empty;
string strPassword = String.Empty;
string strCurrProfileStatus = String.Empty;
if(ProfileLoadReader.HasRows) {
	//считываем данные из запроса
	ProfileLoadReader.Read();
	strCurrProfileID=ProfileLoadReader["id"].ToString();
	strLogin = ProfileLoadReader["login"].ToString();
	strPassword = ProfileLoadReader["password"].ToString();
	strCurrProfileStatus = ProfileLoadReader["status"].ToString();
	project.SendInfoToLog(String.Format("Получили профиль с id: {0} ({1})", strCurrProfileID, strLogin), true);
}else{
	project.SendInfoToLog("Нет ожидающих профилей с заданиями. Завершаем работу", true);
}
ProfileLoadReader.Close();

if (strCurrProfileID!=String.Empty) {
	//помечаем профиль как "занятый" (busy)
	NonQueryDBCommand.CommandText=String.Format("UPDATE db_profiles SET status='busy', last_used=NOW() WHERE id={0};", strCurrProfileID);
	NonQueryDBCommand.ExecuteNonQuery();
}

if (blnLockTables) {
	//снимаем блокировку таблиц
	NonQueryDBCommand.CommandText="UNLOCK TABLES;";
	NonQueryDBCommand.ExecuteNonQuery();
}

//закрываем подключение к БД
ProfileSelectCommand.Connection.Close();

if (strCurrProfileID==String.Empty) return "noprofiles";

//сохраняем id текущего профиля в переменной уровня проекта на случай возникновения ошибки (в этом случае по BadEnd разлочим профиль)
project.Variables["str_current_profile"].Value = strCurrProfileID;

//цикл "выполнения заданий"
int intCompletedTasks = 0; //количество выполненных заданий
do {
	//получаем задание для выполнения
	string strTasksQuery = String.Format("SELECT id, task_type, post_text, post_image, object FROM db_tasks WHERE profile_id={0} AND status='wait' LIMIT 1;", strCurrProfileID);
	string strTask = ZennoPoster.Db.ExecuteQuery(strTasksQuery, null, ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient, strDBConnString, "|", Environment.NewLine);
	if (strTask.Length==0) {
		project.SendInfoToLog(String.Format("Для профиля {0} ({1}) успешно выполнено {2} заданий. Больше в БД заданий для профиля нет, завершаем работу.", strCurrProfileID, strLogin, intCompletedTasks), true);
		break;
	}
	string[] arrTask = strTask.Split('|'); //обратите внимание, в данных таблицы db_tasks не должно быть символов |
	
	//получаем параметры текущего задания
	string strTaskId = arrTask[0];
	string strWhatToDo = arrTask[1];
	string strText = arrTask[2];
	string strImage = arrTask[3];
	string strTaskObject = arrTask[4];
	
	project.SendInfoToLog(String.Format("Выполняем задание id {0} ({1}) для профиля с id {2} ({3})", strTaskId, strWhatToDo, strCurrProfileID, strLogin), true);
	
	//запускаем выполнение задания
	string strTaskResultMessage = String.Empty;
	switch(strWhatToDo) {
		case "post":
			strTaskResultMessage = project.Context["fnPost"](strTaskObject, strText, strImage);
			break;
		case "like":
			strTaskResultMessage = project.Context["fnLike"](strTaskObject);
			break;
		case "invite":
			strTaskResultMessage = project.Context["fnInvite"](strTaskObject);
			break;
	}
	
	//анализируем результат выполнение задания
	string strTaskResult = String.Empty;
	if (strTaskResultMessage.StartsWith("ok:")){
		strTaskResult = "success";
	}else{
		strTaskResult = "error";
	}
	//помечаем задачу выполненной, сохраняем результат выполнения
	ZennoPoster.Db.ExecuteNonQuery(String.Format("UPDATE db_tasks SET status='{0}', status_message='{1}', change_dt=NOW() WHERE id={2};", strTaskResult, strTaskResultMessage, strTaskId), null, ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient, strDBConnString);
	
	if (strTaskResultMessage.Contains("заблокирован")) {
		project.SendWarningToLog(String.Format("Профиль с id {0} ({1}) заблокирован. Завершаем работу", strCurrProfileID, strLogin), true);
		//отменяем все задания в базе для данного профиля (в реальности можно переназначать задания на "любой" профиль)
		ZennoPoster.Db.ExecuteNonQuery(String.Format("UPDATE db_tasks SET status='cancelled', status_message='profile blocked', change_dt=NOW() WHERE profile_id={0} AND status='wait';", strCurrProfileID), null, ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient, strDBConnString);
		strCurrProfileStatus = "blocked"; //меняем статус профиля в переменной на blocked
		break; //прерываем цикл выполнения заданий
	}
	
	intCompletedTasks++;
	
} while (intCompletedTasks<intMaxTasks);

//помечаем профиль как "свободный" (ready). блокировка таблицы при этом не требуется
ZennoPoster.Db.ExecuteNonQuery(String.Format("UPDATE db_profiles SET status='{0}', last_used=NOW() WHERE id={1};", strCurrProfileStatus, strCurrProfileID), null, ZennoLab.InterfacesLibrary.Enums.Db.DbProvider.MySqlClient, strDBConnString);

return "finished";

//ПРИМЕЧАНИЯ:
//1. 

以上是关于csharp Задачадлямногопотокасблокировкойтаблиц的主要内容,如果未能解决你的问题,请参考以下文章

csharp Задачадлямногопотокасблокировкойтаблиц

La Sylphide 仙女

php Добавляемтоварправильно(Сначаладобавляемэлементинфоблока,затемдобавляемэлементторговогокаталога,

php Хрензнаетдлячегоэтафункция,нопоназваниюпонятночтодлядебага

python Скриптпреобразованияматрицызаполняемойпострочновматрицузаполняемуюпоспирали---найденчерезгугл

swift Затемяпопыталсявсе-такитупо,кодомвстиле“Пирамидапогибели”,получитьданныекартинкидля3-хподрядэл