2017-07-24 3 views
0

Ziemlich viele Fragen/Antworten zu diesem Thema (nur ein paar, die ich gefunden habe. Es gab viele mehr).Collection stacking ConcurrentQueue mit Multithreading

  1. C# Parallel - Adding items to the collection being iterated over, or equivalent?
  2. ConcurrentQueue with multithreading

Dank ihnen viele ich habe kommen mit, was ich bin der Hoffnung, eine mögliche Lösung für mein Problem ist. Ich kann es auch überdenken. Ich habe eine API, die in eine Textdatei für Protokollierungszwecke schreiben muss. Jetzt wird die API N + mal aufgerufen und muss bei jedem Aufruf die Anfrage protokollieren. Was ich nicht tun möchte, ist zu verhindern, dass die Anforderung auf das aufzuzeichnende Protokoll warten muss, bevor die angeforderten Daten zurückgegeben werden. Jetzt können die Protokolle nicht einfach gelöscht werden, so dass sie auch bei jeder Anforderung stapeln müssen, wenn die Datei derzeit verwendet wird, wobei hierfür ReaderWriterLock verwendet wird. Wenn die Datei nicht gesperrt ist, möchte ich die gestapelten Protokolle schreiben.

Ich habe dies in der Hoffnung, dass es die Anforderungen erfüllen würde, aber ich denke, es wird immer noch eine Wartezeit verursachen.

var wid = WindowsIdentity.GetCurrent().Token; 
//add new log items 
logs.Enqueue(helpers.createNewLog(requests)); 
string op; 
while (logs.TryDequeue(out op)) 
{ 
    using (WindowsIdentity.Impersonate(wid)) 
    { 
     //write to text file, location on shared drive 
     var wrote = writers.WriteLog(op); 
     //item cannot be written since file locked, add back to queue to try again 
     if (!wrote) 
     { 
      logs.Enqueue(op); 
     } 
    } 
} 

Logs ist ein globaler wie so

private static ConcurrentQueue<string> logs = new ConcurrentQueue<string>(); 

Ich mag das Gefühl etwas nicht in Ordnung ist, aber ich bin zu kämpfen mit dem, was es ist, und die für die Anforderungen wäre der beste Weg, um sich treffen und trotzdem in einer Webfarm arbeiten.

Antwort

1

Meiner Meinung nach sollten Sie eine BlockingCollection statt der ConcurrentQueue verwenden, hier ist ein Beispiel, wie Sie es als Producer-Consumer verwenden können, ist die gleiche Sache, die Sie versuchen zu tun.

Jetzt mit ASP.Net können Sie Module einfügen, um jede Anfrage abzufangen, wenn Sie ein Protokoll speichern möchten, empfehle ich Ihnen, ein Modul zu registrieren, anstatt mit Ihrem Ansatz zu gehen. Auf Ihrem Global.asax.cs haben Sie eine Methode Register

public class MvcApplication : System.Web.HttpApplication 
{ 
    public static void Register() 
    { 
     //registering an HttpModule 
     HttpApplication.RegisterModule(typeof(LogModule)); 
    } 

    .... 
} 


public class LogModule: IHttpModule 
{ 
    public void Dispose() 
    { 

    } 

    public void Init(HttpApplication context) 
    { 
     context.LogRequest += LogEvent; 
    } 

    private void LogEvent(object src, EventArgs args) 
    { 
     if (HttpContext.Current.CurrentNotification == RequestNotification.LogRequest) 
     { 
      if ((MvcHandler)HttpContext.Current.Handler != null) 
      { 
       Debug.WriteLine("This was logged!"); 
       //Save the information to your file 
      } 
     } 
    } 
} 

hoffe, das hilft

+0

würde ich sah schon an der Blocking und fühlte es sich ein bisschen übertrieben war. Ich lag wahrscheinlich falsch, also werde ich noch einen Blick darauf werfen. Danke für die Info zum Modul. –

+0

BlockingCollection verwendet ConcurrentQueue als zugrunde liegenden Speicher standardmäßig. Siehe https://msdn.microsoft.com/en-us/library/dd267312(v=vs.110).aspx –

+0

@TanveerBadar ja du hast Recht, meiner Meinung nach ist es besser zu manipulieren, aber du hast Recht. – Zinov