J'utilise le dataflow de microsoft c'est assez rapide :
ce code creer un personnage sur un autre thread.
public class ActionCreateCharacter : IAction
{
public ActionCreateCharacter( string bic, uint oPC)
{
m_bic = bic;
m_oPC = oPC;
}
public void Run()
{
var memcached = Global.Redis.GetDatabase();
if (memcached.KeyExists(m_bic))
{
return ;
}
using (var db = new Database.DatabaseContext())
{
var query = from pc in db.player_character
where pc.bic == m_bic
select pc;
if (query.Any())
{
var pc = query.First();
memcached.HashSet(m_bic, new HashEntry[] { new HashEntry("first_name", pc.first_name), new HashEntry("last_name", pc.last_name), new HashEntry("race", pc.race) });
return ;
}
Global.CommandBuffer.Post(new CommandGetPlayerCharacterInfo(m_oPC, m_infoBlock));
m_infoBlock.OutputAvailableAsync().Wait();
var info = m_infoBlock.Receive();
var data = db.player_character.CreateObject();
data.bic = m_bic;
data.first_name = info.firstName;
data.last_name = info.lastName;
data.race = info.race;
db.player_character.AddObject(data);
db.SaveChanges();
memcached.HashSet(m_bic, new HashEntry[] { new HashEntry("first_name", info.firstName), new HashEntry("last_name", info.lastName), new HashEntry("race", info.race) });
}
}
string m_bic;
uint m_oPC;
WriteOnceBlock<playerCharacterInfo> m_infoBlock = new WriteOnceBlock<playerCharacterInfo>(null);
}
public void Init()
{
m_actionQueue.Post(new ActionCreateCharacter(m_bic,m_oPC));
}
public ActionBlock<IAction> m_actionQueue = new ActionBlock<IAction>((action) => { action.Run(); });
J'execute un script toutes les 30/ 100 de secondes qui consomme les commande qui sont mis en mémoire dans le buffer.
using NWScript.ManagedInterfaceLayer.NWScriptManagedInterface;
using IronKingdoms;
using System.Threading;
using System.Threading.Tasks.Dataflow;
using NWEffect = NWScript.NWScriptEngineStructure0;
using NWEvent = NWScript.NWScriptEngineStructure1;
using NWLocation = NWScript.NWScriptEngineStructure2;
using NWTalent = NWScript.NWScriptEngineStructure3;
using NWItemProperty = NWScript.NWScriptEngineStructure4;
namespace IronKingdoms
{
public partial class update : CLRScriptBase, ICLRScriptImplementation, IGeneratedScriptProgram
{
public update([In] NWScriptJITIntrinsics Intrinsics, [In] INWScriptProgram Host)
{
InitScript(Intrinsics, Host);
}
private update([In] update Other)
{
InitScript(Other);
LoadScriptGlobals(Other.SaveScriptGlobals());
}
//
// Include the list of types for parameters to the main function here.
// An empty list means no parameters.
//
public static Type[] ScriptParameterTypes = { };
public Int32 ScriptMain([In] object[] ScriptParameters, [In] Int32 DefaultReturnCode)
{
IList<ICommand> commandList;
if (Global.CommandBuffer.TryReceiveAll(out commandList))
{
foreach (var command in commandList)
{
command.Run(this);
}
}
DelayCommand(0.03f, delegate() { ExecuteScript(SCRIPT_NAME, OBJECT_SELF); });
return DefaultReturnCode;
}
private const string SCRIPT_NAME = "update";
}
}
les classes necessaires :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using StackExchange.Redis;
using CLRScriptFramework;
namespace IronKingdoms
{
public static class Global
{
public static ConnectionMultiplexer Redis = ConnectionMultiplexer.Connect("localhost");
public static BufferBlock<ICommand> CommandBuffer = new BufferBlock<ICommand>();
}
public interface IAction
{
void Run();
}
public interface ICommand
{
void Run(CLRScriptBase scriptBase);
}
}
public struct playerCharacterInfo
{
public string firstName;
public string lastName;
public int race;
}
public class CommandGetPlayerCharacterInfo : ICommand
{
public CommandGetPlayerCharacterInfo(uint oPC, WriteOnceBlock<playerCharacterInfo> infoBlock)
{
m_oPC = oPC;
m_infoBlock = infoBlock;
}
public void Run( CLRScriptBase scriptBase)
{
playerCharacterInfo info;
info.firstName = scriptBase.GetFirstName(m_oPC);
info.lastName = scriptBase.GetLastName(m_oPC);
info.race = scriptBase.GetRacialType(m_oPC);
m_infoBlock.Post(info);
}
uint m_oPC;
WriteOnceBlock<playerCharacterInfo> m_infoBlock;
}