I want to make ActionResult with run a thread. When thread are running I will return View with loading but when thread finished the ActionResult return the another View
My code look like:
private static void ExecuteScrapper()
{
ScriptEngine pythonEngine = IronPython.Hosting.Python.CreateEngine();
ScriptSource pythonScript = pythonEngine.CreateScriptSourceFromFile(HostingEnvironment.MapPath("/PythonScript/main.py"));
var searchPath = pythonEngine.GetSearchPaths();
searchPath.Add(HostingEnvironment.MapPath("/PythonScript/"));
searchPath.Add(HostingEnvironment.MapPath("/PythonScript/drivers/"));
pythonEngine.SetSearchPaths(searchPath);
var result = pythonScript.Execute();
}
private ScrapperEnum.ScrapperOperations scraperParam;
private Thread t = new Thread(new ThreadStart(ExecuteScrapper));
public ActionResult RunScrapper(ScrapperEnum.ScrapperOperations operation)
{
scraperParam = operation;
t.Start();
bool run = false;
while(t.IsAlive)
{
if(!run)
{
run = true;
return View("ScrapperLoadingView");
}
}
return RedirectToAction("Scrapper");
}
I don't know exactly how to do that, because when in this code I return ScrapperLoginView it will break while so the function don't switch the View
You just need to add an else if I'm correct
while(t.IsAlive)
{
if(!run)
{
run = true;
return View("ScrapperLoadingView");
}
else
{
return RedirectToAction("Scrapper");
}
}
}
Related
I am using Asp.Net core 3.1 . If I want to create a WebSockets backend for example for
a chat app , I need to store all the related WebSocket objects for broadcasting events , my question is what is the best way to manage removing objects that are no longer useful (if disconnected or no longer open). keeping in mind that I want other parts of the application to access the WebScoket groups to also broadcast events if needed. I store the related connections in a ConnectionNode which is the nearest layer to the Websocket objects , a class called WebsocketsManager manage these nodes, a service in the background runs to clear the unused objects every timeout period. but since I want the group(related connections)to be accessible for the application (for example other endpoints); to avoid any concurrent modification errors , if a broadcast is required during the cleaning process,the broadcast will have to wait for the cleaning process to finish, thats why the WebsocketsManager if the related connections are larger than a certain limit it will divide them into multiple related ConnectionNodes , that way the cleaning process can continue partially for related connection while broadcasting if needed. I want to know how good my solution will behave or what is the best way to do it. any help would be really appreciated.
ConnectionNode
public class ConnectionNode
{
private List<WebSocket> connections;
private BroadcastQueue BroadcastQueue = new BroadcastQueue();
private bool isBroadCasting = false;
private bool isCleaning = false;
public void AddConnection(WebSocket socket)
{
if (connections == null)
connections = new List<WebSocket>();
connections.Add(socket);
}
public void Broadcast(Broadcast broadCast)
{
while (isCleaning)
{
}
BroadcastQueue.QueueBroadcast(broadCast);
if (isBroadCasting)
{
return;
}
isBroadCasting = true;
var broadcast = BroadcastQueue.GetNext();
while (broadCast != null)
{
foreach (var ws in connections)
{
broadCast.Dispatch(ws);
}
broadCast = BroadcastQueue.GetNext();
}
isBroadCasting = false;
}
public int CleanUnUsedConnections()
{
if (isBroadCasting)
return 0;
isCleaning = true;
var i =connections.RemoveAll(s => s.State != WebSocketState.Open);
isCleaning = false;
return i;
}
public int ConnectionsCount()
{
return connections.Count;
}
}
Manager class
public class WebSocketsManager
{
static int ConnectionNodesDividerLimit = 1000;
private ConcurrentDictionary<String, List<ConnectionNode>> mConnectionNodes;
private readonly ILogger<WebSocketsManager> logger;
public WebSocketsManager(ILogger<WebSocketsManager> logger)
{
this.logger = logger;
}
public ConnectionNode RequireNode(string Id)
{
if (mConnectionNodes == null)
mConnectionNodes = new ConcurrentDictionary<String, List<ConnectionNode>>();
var node = mConnectionNodes.GetValueOrDefault(Id);
if (node == null)
{
node = new List<ConnectionNode>();
node.Add(new ConnectionNode());
mConnectionNodes.TryAdd(Id, node);
return node[0];
}
if (ConnectionNodesDividerLimit != 0)
{
if (node[0].ConnectionsCount() == ConnectionNodesDividerLimit)
{
node.Insert(0,new ConnectionNode());
}
}
return node[0];
}
public void ClearUnusedConnections()
{
logger.LogInformation("Manager is Clearing ..");
if (mConnectionNodes == null)
return;
if (mConnectionNodes.IsEmpty)
{
logger.LogInformation("Empty ## Nothing to clear ..");
return;
}
Dictionary<String,ConnectionNode> ToBeRemovedNodes = new Dictionary<String, ConnectionNode>();
foreach (var pair in mConnectionNodes)
{
bool shoudlRemoveStack = true;
foreach (var node in pair.Value)
{
int i = node.CleanUnUsedConnections();
logger.LogInformation($"Removed ${i} from connection node(s){pair.Key}");
if (node.ConnectionsCount() == 0)
{
ToBeRemovedNodes[pair.Key] = node;
logger.LogInformation($"To be Removed A node From ..{pair.Key}");
}
else
{
shoudlRemoveStack = false;
}
}
if (shoudlRemoveStack)
{
ToBeRemovedNodes.Remove(pair.Key);
List<ConnectionNode> v =null;
var b = mConnectionNodes.TryRemove(pair.Key,out v);
logger.LogInformation($"Removing the Stack ..{pair.Key} Removed ${b}");
}
}
foreach (var pair in ToBeRemovedNodes)
{
mConnectionNodes[pair.Key].Remove(pair.Value);
logger.LogInformation($"Clearing Nodes : Clearing Nodes from stack #{pair.Key}");
}
}
public void Broadcast(string id, Broadcast broadcast)
{
var c = mConnectionNodes.GetValueOrDefault(id);
foreach (var node in c)
{
node.Broadcast(broadcast);
}
}
the service
public class SocketsConnectionsCleaningService : BackgroundService
{
private readonly IServiceProvider Povider;
private Timer Timer = null;
private bool isRunning = false;
private readonly ILogger Logger;
public SocketsConnectionsCleaningService(IServiceProvider Provider, ILogger<SocketsConnectionsCleaningService> Logger )
{
this.Povider = Provider;
this.Logger = Logger;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
Logger.LogInformation("Execute Sync is called ");
Timer = new Timer(DeleteClosedConnections, null, TimeSpan.FromMinutes(0), TimeSpan.FromMinutes(2));
return Task.CompletedTask;
}
private void DeleteClosedConnections(object state)
{
Logger.LogInformation("Clearing ");
if (isRunning)
{
Logger.LogInformation("A Task is Running Return ");
return;
}
isRunning = true;
var connectionManager = Povider.GetService(typeof(WebSocketsManager)) as WebSocketsManager;
connectionManager.ClearUnusedConnections();
isRunning = false;
Logger.LogInformation($"Finished Cleaning !");
}
}
Usage in a controller be like
[HttpGet("ws")]
public async Task SomeRealtimeFunction()
{
if (HttpContext.IsWebSocketsRequest())
{
using var socket = await HttpContext.AcceptSocketRequest();
try
{
await socket.SendString(" Connected! ");
webSocketsManager.RequireNode("Chat Room")
.AddConnection(socket);
var RecieverHelper = socket.GetRecieveResultsHelper();
string str = await RecieverHelper.ReceiveString();
while (!RecieverHelper.Result.CloseStatus.HasValue)
{
webSocketsManager
.Broadcast("Chat Room", new StringBroadcast(str));
str = await RecieverHelper.ReceiveString();
}
}
catch (Exception e)
{
await socket.SendString("Error!");
await socket.SendString(e.Message);
await socket.SendString(e.ToString());
}
}
else
{
HttpContext.Response.StatusCode = 400;
}
}
I have a asp.net web site. I have an image being updated via a timer as many times as possible every second with an image the size of 720x576. I control when the image can be updated by initiating the next ashx page call to get my image after the img control has finished loading the previous image (I do this on the 'onload' event).
My w3wp.exe currently stands at 140,000k and it drops to 130,000. Frequently going up and down between these 2 values.
As i am testing with 1 User and as I am on a cheap VPS shared hosting environment my question is when I go Live will the w3wp.exe become uncontrollable or will the fact that by upgrading my server package (mainly increasing RAM) help to keep this all under control n a multi-user environment?
This is my Javascript:
var timer3;
var intervalLive = 50;
function play2() {
if (timer3) window.clearTimeout(timer3);
swapImages3();
}
function setImageSrc3(src) {
_imgLive.src = src;
timer3 = window.setTimeout(swapImages3, intervalLive);
}
function swapImages3() {
var imgCached = new Image();
imgCached.onload = function () {
setImageSrc3(imgCached.src);
};
imgCached.onerror = function () {
setImageSrc3("http://a URL/images/ERROR.jpg");
};
imgCached.onload = function () {
setImageSrc3(imgCached.src);
};
imgCached.src = null;
imgCached.src = 'http://A URL/Cloud/LiveXP.ashx?id=' + new Date().getTime() + '&Alias=' + alias;
}
And this is in my ashx page:
public class Live : IHttpHandler {
DAL dal = new DAL();
static byte[] StandardError = Shared.ERROR;
public void ProcessRequest(HttpContext context)
{
byte[] data = null;
context.Response.ContentType = "image/jpg";
try
{
if (context.Request.QueryString["Alias"] != null)
{
data = Shared.GetFrame(context.Request.QueryString["Alias"].ToString());
context.Response.BinaryWrite(data);
}
}
catch (Exception ex)
{
data = StandardError;
dal.AddError(ex.ToString());
}
finally
{
context.Response.BinaryWrite(data);
}
}
public bool IsReusable {
get {
return true;
}
}
}
thanks
I am writing a Metro App.
I am trying to read a file and return a float[] from the data. But no matter what I do, the function seems to return null. I have tried the solutions to similar questions to no luck.
For example if I use:
float[] floatArray = new ModelReader("filename.txt").ReadModel()
The result will be a null array.
However if I use:
new ModelReader("filename.txt")
The correct array will be printed to the console because "Test" also prints the array before returning it. This seems very weird to me.
Please give me some guidance, I have no idea what is wrong.
public class ModelReader
{
float[] array;
public ModelReader(String name)
{
ReadModelAsync(name);
}
public float[] ReadModel()
{
return array;
}
private async Task ReadModelAsync(String name)
{
await readFile(name);
}
async Task readFile(String name)
{
// settings
var path = #"Assets\models\" + name;
var folder = Windows.ApplicationModel.Package.Current.InstalledLocation;
// acquire file
var file = await folder.GetFileAsync(path);
// read content
var read = await Windows.Storage.FileIO.ReadTextAsync(file);
using (StringReader sr = new StringReader(read))
{
Test test = new Test(getFloatArray(sr));
this.array = test.printArray();
}
}
private float[] getFloatArray(StringReader sr) { ... }
public class Test
{
public float[] floatArray;
public Test(float[] floatArray)
{
this.floatArray = floatArray;
}
public float[] printArray()
{
for (int i = 0; i < floatArray.Length; i++)
{
Debug.WriteLine(floatArray[i]);
}
return floatArray;
}
}
You're trying to get the result of an asynchronous operation before it has completed. I recommend you read my intro to async / await and follow-up with the async / await FAQ.
In particular, your constructor:
public ModelReader(String name)
{
ReadModelAsync(name);
}
is returning before ReadModelAsync is complete. Since constructors cannot be asynchronous, I recommend you use an asynchronous factory or asynchronous lazy initialization as described on my blog (also available in my AsyncEx library).
Here's a simple example using an asynchronous factory approach:
public class ModelReader
{
float[] array;
private ModelReader()
{
}
public static async Task<ModelReader> Create(string name)
{
var ret = new ModelReader();
await ret.ReadModelAsync(name);
return ret;
}
...
}
"How can i use engine in my console application"
I shouldn't use the ITemplate-interface and Transform-Method.
I am using Tridion 2011
Could anyone please suggest me.
You can't. The Engine class is part of the TOM.NET and that API is explicitly reserved for use in:
Template Building Blocks
Event Handlers
For all other cases (such as console applications) you should use the Core Service.
There are many good questions (and articles on other web sites) already:
https://stackoverflow.com/search?q=%5Btridion%5D+core+service
http://www.google.com/#q=tridion+core+service
If you get stuck along the way, show us the relevant code+configuration you have and what error message your get (or at what step you are stuck) and we'll try to help from there.
From a console application you should use the Core Service. I wrote a small example using the Core Service to search for items in the content manager.
Console.WriteLine("FullTextQuery:");
var fullTextQuery = Console.ReadLine();
if (String.IsNullOrWhiteSpace(fullTextQuery) || fullTextQuery.Equals(":q", StringComparison.OrdinalIgnoreCase))
{
break;
}
Console.WriteLine("SearchIn IdRef:");
var searchInIdRef = Console.ReadLine();
var queryData = new SearchQueryData
{
FullTextQuery = fullTextQuery,
SearchIn = new LinkToIdentifiableObjectData
{
IdRef = searchInIdRef
}
};
var results = coreServiceClient.GetSearchResults(queryData);
results.ToList().ForEach(result => Console.WriteLine("{0} ({1})", result.Title, result.Id));
Add a reference to Tridion.ContentManager.CoreService.Client to your Visual Studio Project.
Code of the Core Service Client Provider:
public interface ICoreServiceProvider
{
CoreServiceClient GetCoreServiceClient();
}
public class CoreServiceDefaultProvider : ICoreServiceProvider
{
private CoreServiceClient _client;
public CoreServiceClient GetCoreServiceClient()
{
return _client ?? (_client = new CoreServiceClient());
}
}
And the client itself:
public class CoreServiceClient : IDisposable
{
public SessionAwareCoreServiceClient ProxyClient;
private const string DefaultEndpointName = "netTcp_2011";
public CoreServiceClient(string endPointName)
{
if(string.IsNullOrWhiteSpace(endPointName))
{
throw new ArgumentNullException("endPointName", "EndPointName is not specified.");
}
ProxyClient = new SessionAwareCoreServiceClient(endPointName);
}
public CoreServiceClient() : this(DefaultEndpointName) { }
public string GetApiVersionNumber()
{
return ProxyClient.GetApiVersion();
}
public IdentifiableObjectData[] GetSearchResults(SearchQueryData filter)
{
return ProxyClient.GetSearchResults(filter);
}
public IdentifiableObjectData Read(string id)
{
return ProxyClient.Read(id, new ReadOptions());
}
public ApplicationData ReadApplicationData(string subjectId, string applicationId)
{
return ProxyClient.ReadApplicationData(subjectId, applicationId);
}
public void Dispose()
{
if (ProxyClient.State == CommunicationState.Faulted)
{
ProxyClient.Abort();
}
else
{
ProxyClient.Close();
}
}
}
When you want to perform CRUD actions through the core service you can implement the following methods in the client:
public IdentifiableObjectData CreateItem(IdentifiableObjectData data)
{
data = ProxyClient.Create(data, new ReadOptions());
return data;
}
public IdentifiableObjectData UpdateItem(IdentifiableObjectData data)
{
data = ProxyClient.Update(data, new ReadOptions());
return data;
}
public IdentifiableObjectData ReadItem(string id)
{
return ProxyClient.Read(id, new ReadOptions());
}
To construct a data object of e.g. a Component you can implement a Component Builder class that implements a create method that does this for you:
public ComponentData Create(string folderUri, string title, string content)
{
var data = new ComponentData()
{
Id = "tcm:0-0-0",
Title = title,
Content = content,
LocationInfo = new LocationInfo()
};
data.LocationInfo.OrganizationalItem = new LinkToOrganizationalItemData
{
IdRef = folderUri
};
using (CoreServiceClient client = provider.GetCoreServiceClient())
{
data = (ComponentData)client.CreateItem(data);
}
return data;
}
Hope this gets you started.
I have run into this problem across multiple programming languages and I was just wondering what the best way to handle it is.
I have three method calls that fire off asynchronously. Each one has a callback. I want to do something only when all three callbacks have completed.
What is the best way to code this? I usually end up with all these public bool flags and as you add more calls the code gets more convoluted.
Coming from C#, I would probably use WaitHandle.WaitAll. You can create an array of ManualResetEvent objects (one for each task to be completed), and pass that array to WaitAll. The threaded tasks will get one ManualResetEvent object each, and call the Set method when they are ready. WaitAll will block the calling thread until all tasks are done. I'll give a C# code example:
private void SpawnWorkers()
{
ManualResetEvent[] resetEvents = new[] {
new ManualResetEvent(false),
new ManualResetEvent(false)
};
// spawn the workers from a separate thread, so that
// the WaitAll call does not block the main thread
ThreadPool.QueueUserWorkItem((state) =>
{
ThreadPool.QueueUserWorkItem(Worker1, resetEvents[0]);
ThreadPool.QueueUserWorkItem(Worker2, resetEvents[1]);
WaitHandle.WaitAll(resetEvents);
this.BeginInvoke(new Action(AllTasksAreDone));
});
}
private void AllTasksAreDone()
{
// OK, all are done, act accordingly
}
private void Worker1(object state)
{
// do work, and then signal the waiting thread
((ManualResetEvent) state).Set();
}
private void Worker2(object state)
{
// do work, and then signal the waiting thread
((ManualResetEvent)state).Set();
}
Note that the AllTasksAreDone method will execute on the thread pool thread that was used to spawn the workers, and not on the main thread... I assume that many other languages have similar constructs.
If you really only want to wait for all to finish:
Create volatile counter
Synchronize access to counter
Increase counter on start
Decrease on callback fired
Wait for counter to reach 0
Use a semaphore.
Futures are very easy to use. Futures look like normal functions, except that they execute asynch.
The classes:
public struct FutureResult<T>
{
public T Value;
public Exception Error;
}
public class Future<T>
{
public delegate R FutureDelegate<R>();
public Future(FutureDelegate<T> del)
{
_del = del;
_result = del.BeginInvoke(null, null);
}
private FutureDelegate<T> _del;
private IAsyncResult _result;
private T _persistedValue;
private bool _hasValue = false;
private T Value
{
get
{
if (!_hasValue)
{
if (!_result.IsCompleted)
_result.AsyncWaitHandle.WaitOne();
_persistedValue = _del.EndInvoke(_result);
_hasValue = true;
}
return _persistedValue;
}
}
public static implicit operator T(Future<T> f)
{
return f.Value;
}
}
Here I use futures to simulate a deadlock:
void SimulateDeadlock()
{
Future> deadlockFuture1 = new Future>(() =>
{
try
{
new SystemData(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)
.SimulateDeadlock1(new DateTime(2000, 1, 1, 0, 0, 2));
return new FutureResult { Value = true };
}
catch (Exception ex)
{
return new FutureResult { Value = false, Error = ex };
}
});
Future> deadlockFuture2 = new Future>(() =>
{
try
{
new SystemData(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)
.SimulateDeadlock2(new DateTime(2000, 1, 1, 0, 0, 2));
return new FutureResult { Value = true };
}
catch (Exception ex)
{
return new FutureResult { Value = false, Error = ex };
}
});
FutureResult result1 = deadlockFuture1;
FutureResult result2 = deadlockFuture2;
if (result1.Error != null)
{
if (result1.Error is SqlException && ((SqlException)result1.Error).Number == 1205)
Console.WriteLine("Deadlock!");
else
Console.WriteLine(result1.Error.ToString());
}
else if (result2.Error != null)
{
if (result2.Error is SqlException && ((SqlException)result2.Error).Number == 1205)
Console.WriteLine("Deadlock!");
else
Console.WriteLine(result2.Error.ToString());
}
}
For those using JavaScript, consider using the pattern discussed at this Stackoverflow question:
javascript: execute a bunch of asynchronous method with one callback