The System.Threading.EventWaitHandle type does not contain a definition for 'dispose'.
How am I supposed to dispose of the EventWaitHandle when I want to kill the object in which it is contained? I've been having a serious memory leak problem and I've tried setting the EventWaitHandle to null and the memory leak persists.
Here's my code (I'm using Bob Craven's library, I added only the dispose() method):
using System;
using System.Threading;
namespace Rlc.Cron
{
public class CronObject
{
public delegate void CronEvent(CronObject cronObject);
public event CronEvent OnCronTrigger;
public event CronEvent OnStarted;
public event CronEvent OnStopped;
public event CronEvent OnThreadAbort;
private CronObjectDataContext _cronObjectDataContext;
private Guid _id = Guid.NewGuid();
private object _startStopLock = new object();
private EventWaitHandle _wh = new AutoResetEvent(false);
private Thread _thread;
public bool _isStarted;
private bool _isStopRequested;
private DateTime _nextCronTrigger;
public Guid Id { get { return _id; } }
public object Object { get { return _cronObjectDataContext.Object; } }
public DateTime LastTigger { get { return _cronObjectDataContext.LastTrigger; } }
/// <summary>
/// Initializes a new instance of the <see cref="CronObject"/> class.
/// </summary>
/// <param name="cronObjectDataContext">The cron object data context.</param>
public CronObject(CronObjectDataContext cronObjectDataContext)
{
if (cronObjectDataContext == null)
{
throw new ArgumentNullException("cronObjectDataContext");
}
if (cronObjectDataContext.Object == null)
{
throw new ArgumentException("cronObjectDataContext.Object");
}
if (cronObjectDataContext.CronSchedules == null || cronObjectDataContext.CronSchedules.Count == 0)
{
throw new ArgumentException("cronObjectDataContext.CronSchedules");
}
_cronObjectDataContext = cronObjectDataContext;
}
/// <summary>
/// Starts this instance.
/// </summary>
/// <returns></returns>
public bool Start()
{
lock (_startStopLock)
{
// Can't start if already started.
//
if (_isStarted)
{
return false;
}
_isStarted = true;
_isStopRequested = false;
// This is a long running process. Need to run on a thread
// outside the thread pool.
//
_thread = new Thread(ThreadRoutine);
_thread.Start();
}
// Raise the started event.
//
if(OnStarted != null)
{
OnStarted(this);
}
return true;
}
/// <summary>
/// Stops this instance.
/// </summary>
/// <returns></returns>
public bool Stop()
{
lock (_startStopLock)
{
// Can't stop if not started.
//
if (!_isStarted)
{
return false;
}
_isStarted = false;
_isStopRequested = true;
// Signal the thread to wake up early
//
_wh.Set();
// Wait for the thread to join.
//
if(!_thread.Join(5000))
{
_thread.Abort();
// Raise the thread abort event.
//
if(OnThreadAbort != null)
{
OnThreadAbort(this);
}
}
}
// Raise the stopped event.
//
if(OnStopped != null)
{
OnStopped(this);
}
return true;
}
public void dispose(){
this.Stop ();
this.OnCronTrigger = null;
this.OnStarted=null;
this.OnStopped=null;
this.OnThreadAbort=null;
this._cronObjectDataContext=null;
this._startStopLock = null;
this._wh = null;
this._thread=null;
}
/// <summary>
/// Cron object thread routine.
/// </summary>
private void ThreadRoutine()
{
// Continue until stop is requested.
//
while(!_isStopRequested)
{
// Determine the next cron trigger
//
DetermineNextCronTrigger(out _nextCronTrigger);
TimeSpan sleepSpan = _nextCronTrigger - DateTime.Now;
if(sleepSpan.TotalMilliseconds < 0)
{
// Next trigger is in the past. Trigger the right away.
//
sleepSpan = new TimeSpan(0, 0, 0, 0, 50);
}
// Wait here for the timespan or until I am triggered
// to wake up.
//
if(!_wh.WaitOne(sleepSpan))
{
// Timespan is up...raise the trigger event
//
if(OnCronTrigger != null)
{
OnCronTrigger(this);
}
// Update the last trigger time.
//
_cronObjectDataContext.LastTrigger = DateTime.Now;
}
}
}
/// <summary>
/// Determines the next cron trigger.
/// </summary>
/// <param name="nextTrigger">The next trigger.</param>
private void DetermineNextCronTrigger(out DateTime nextTrigger)
{
nextTrigger = DateTime.MaxValue;
foreach (CronSchedule cronSchedule in _cronObjectDataContext.CronSchedules)
{
DateTime thisTrigger;
if(cronSchedule.GetNext(LastTigger, out thisTrigger))
{
if (thisTrigger < nextTrigger)
{
nextTrigger = thisTrigger;
}
}
}
}
~CronObject(){
Console.WriteLine ("===================CRONOBJECT DESTROYED!!===============");
}
}
}
Related
I try to get this work correct but wen i start to stream it contious repeat the image video.
I need it stream only one video.
The problem is wen i start to stream the video image it continous repeat the video, how can i stop the player to not repeat the image and only Get one.
This is what i get wen i start and i want to avoid the video to continuous repeating the video
I have edit and my script and add the lines of code
But It Continous Repeat The Video With Out Stop
This is my script
using UnityEngine;
using System;
using MP;
using MP.Net;
/// <summary>
/// Movie streamer
/// </summary>
public class MovieStreamer : MoviePlayerBase
{
#region ----- public ------
/// <summary>
/// Movie source url
/// </summary>
public string sourceUrl;
/// <summary>
/// Movie load options. The Load() methods on this component will use
/// this unless you're provinding your own.
/// </summary>
public LoadOptions loadOptions = LoadOptions.Default;
/// <summary>
/// Background thread status
/// </summary>
public string status;
public long bytesReceived;
public bool IsConnected
{
get {
return movie==null || movie.demux==null ? false : ((Streamer)movie.demux).IsConnected;
}
}
/// <summary>
/// Connects to an URL for streaming.
///
/// In case it fails, exception text is logged and FALSE is returned
/// </summary>
public bool Load (string srcUrl)
{
return Load (srcUrl, null);
}
public bool Load (string srcUrl, LoadOptions loadOptions)
{
this.sourceUrl = srcUrl;
if(loadOptions == null) {
loadOptions = this.loadOptions;
} else {
this.loadOptions = loadOptions;
}
try {
base.Load(new MovieSource() { url = srcUrl }, loadOptions);
return true;
}
catch (Exception e) {
if(loadOptions.enableExceptionThrow) {
throw e;
} else {
Debug.LogError (e);
return false;
}
}
}
[ContextMenu("Reconnect")]
public bool ReConnect ()
{
bool success = true;
if (!string.IsNullOrEmpty(sourceUrl)) {
success = Load (sourceUrl, loadOptions);
}
return success;
}
#endregion ------ / public ------
#region ----- private -----
private int lastVideoFrame = -1;
void Start ()
{
ReConnect ();
}
void OnGUI ()
{
if (!IsConnected || !movie.demux.hasVideo)
return;
// if we're playing the movie directly to screen, but don't
// show it before we've received at least one frame
if (drawToScreen && framebuffer != null && ((Streamer)movie.demux).VideoPosition > 0) {
DrawFramebufferToScreen ();
}
}
void Update ()
{
// get the thread status and write it here
if(movie != null && movie.demux != null)
{
if(movie.demux is HttpMjpegStreamer) {
status = ((HttpMjpegStreamer)movie.demux).Status;
bytesReceived = ((HttpMjpegStreamer)movie.demux).BytesReceived;
}
}
// if this.play changed, Play or Stop the movie
HandlePlayStop ();
// decode a frame when necessary
if(play) {
HandleFrameDecode ();
DrawFramebufferToScreen();
HandlePlayStop();
}
}
protected void HandleFrameDecode ()
{
if (!IsConnected || !movie.demux.hasVideo || movie.videoDecoder == null)
return;
// decode a frame if there's a new one available
if (movie.videoDecoder.Position != lastVideoFrame)
{
if(movie.videoDecoder.Position >= 0)
{
movie.videoDecoder.DecodeNext ();
// update the aspect ration of the video
movie.demux.videoStreamInfo.width = framebuffer.width;
movie.demux.videoStreamInfo.height = framebuffer.height;
}
lastVideoFrame = movie.videoDecoder.Position;
}
}
#endregion
}
I have SinglaR hub class "MyHub" and a .net client class that connects to it successfully in runtime. however when i'm testing the client with nunit test it doesn't connect, I've debugged the test and find that hub instance doesn't created by SinglaR's hub activator class.
I'm using Resharper nunit runner for running test.
Here is my hub class structure, i've remove method's body for simplicity.
[HubName("myHub")]
public class MyHub : Hub
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(MyHub));
#region MyRegion
#region Connection Methods
public MyHub()
{
}
private static int c;
public override Task OnConnected()
{
}
private string UserNameConnectionId
{
}
public override Task OnReconnected()
{
lock (LockObject)
{
}
}
public override Task OnDisconnected(bool b)
{
lock (LockObject)
{
}
}
private void LogUserActivity(string userName, string activity)
{
}
#endregion
//Live controls invoke this Method to send their required data and also their ConnectionId
/// <summary>
/// </summary>
/// <param name="liveControlsInfo"></param>
public Task UpdateLiveControlsInfo(LiveControlInfo[] liveControlsInfo)
{
lock (LockObject)
{
}
}
public string GetValue()
{
return "SignalR Rox!";
}
public void Acknowledge()
{
lock (LockObject)
{
string connectionId = Context.ConnectionId;
}
}
}
#endregion
}
}
here is HubWinClient class
public class HubWinClient
{
private readonly string _userName;
public int ServerPort { get; set; }
private static readonly ILog logger = LogManager.GetLogger(typeof (HubWinClient));
protected int HubLogCounter = 0;
private HubConnection connection;
private bool moduleStarted;
private IHubProxy myHub;
public HubWinClient(int serverPort, string userName= "Windows Hub Client", bool tryConnect=false)
{
_userName = userName;
ServerPort = serverPort;
}
public void Start()
{
ConnectToHub();
moduleStarted = true;
}
public void Stop()
{
DisconnectFromHub();
moduleStarted = false;
}
public void ConnectToHub()
{
ConnectToHub(false);
}
public event EventHandler<EventArgs> ConnectingToHub = delegate { };
public event EventHandler<EventArgs> ConnectedToHub = delegate { };
/// <summary>
/// callback event called by hubhost
/// </summary>
public event EventHandler<int> LogSentToHub = delegate { };
public event EventHandler<EventArgs> DisonnectedFromHub = delegate { };
public event EventHandler<EventArgs> HubConnectionError = delegate { };
public event EventHandler<EventArgs> HubInvokeError = delegate { };
public event EventHandler<EventArgs> HubInvokeSuccess = delegate { };
public event EventHandler<EventArgs> NotConnectedToSentLog = delegate { };
public event EventHandler<LogMessage> DataRecivedFromHub = delegate { };
/// <summary>
/// connects HunNotifier to Hun in order to ListenerMessage passing can be done
/// </summary>
/// <param name="reconnect"></param>
private void ConnectToHub(bool reconnect)
{
//This url will not point to a specific connection. But will instead point to the root of your site=root of hub server.
string hubAddress = "http://localhost:" + ServerPort;
connection = new HubConnection(hubAddress, new Dictionary<string, string>{{"UserName", _userName } });
ConnectingToHub(this, new EventArgs());
if (reconnect)
logger.InfoFormat("HubWinClient reconnecting to HubHost # {0}...", hubAddress);
else
logger.InfoFormat("HubWinClient connecting to HubHost # {0}...", hubAddress);
myHub = connection.CreateHubProxy("myHub");
myHub.On("joined", joined);
myHub.On("rejoined", rejoined);
myHub.On("leaved", leaved);
myHub.On<LogMessage>("addData", addData);
myHub.On<int>("LogSentToWeb", LogSentToWeb);
connection.StateChanged += change =>
{
var a = change;
var b = 10;
var a1 = connection.LastError;
var b2 = connection.Proxy;
};
try
{
connection.Start();
}
catch (AggregateException aggregateException)
{
Exception exception = aggregateException.InnerException;
logger.Error("HubWinClient connection to HubHost exception...", exception);
HubConnectionError(this, new MyEventArgs {Exception = exception});
}
catch (Exception exception)
{
logger.Error("HubWinClient connection to HubHost exception...", exception);
HubConnectionError(this, new MyEventArgs {Exception = exception});
}
}
public void DisconnectFromHub()
{
connection.Stop();
}
/// <summary>
/// when hub notifier connected to hub, hub invoke this method to inform connection success.
/// </summary>
public void joined()
{
var liveControlInfo = new LiveControlInfo
{
LiveControlType = LiveControlType.mainClient
};
// myHub.Invoke("AddLiveControl", liveControlInfo).Wait();
// logger.Info("HubWinClient joined");
ConnectedToHub(this, new EventArgs());
}
/// <summary>
/// when hub notifier reconnected to hub, hub invoke this method to inform reconnection success.
/// </summary>
public void rejoined()
{
logger.Info("HubWinClient rejoined");
}
/// <summary>
/// when hub notifier disconnect from hub, hub invoke this method to inform disconnection.
/// </summary>
public void leaved()
{
logger.Info("HubWinClient disconnected");
DisonnectedFromHub(this, new EventArgs());
}
public void addData(LogMessage logMessage)
{
DataRecivedFromHub(this, logMessage);
}
public event EventHandler<LogMessage> OnSendingLogToHub = delegate { };
/// <summary>
/// called by HubClientMoudle when it's ApplyLogReceived are invoked by WCF service
/// </summary>
/// <param name="logMessage"></param>
public void SendToHub(LogMessage logMessage)
{
OnSendingLogToHub(this, logMessage);
if (!moduleStarted) return;
if (connection.State != ConnectionState.Connected)
ConnectToHub(true);
if (connection.State == ConnectionState.Connected)
{
if (System.Diagnostics.Debugger.IsAttached ||
Math.Abs((logMessage.Log.ArrivalDateTime - DateTime.Now).Ticks) < TimeSpan.FromMinutes(10).Ticks)
{
try
{
Task task = myHub.Invoke("send", logMessage);
task.Wait(5000);
logger.Debug("Send log success");
HubInvokeSuccess(this, new EventArgs());
}
catch (AggregateException aggregateException)
{
Exception exception = aggregateException.InnerException;
logger.Error("Send log Exceotion!", exception);
HubInvokeError(this, new MyEventArgs {Exception = exception});
}
catch (Exception exception)
{
logger.Error("Send log Exceotion!", exception);
HubInvokeError(this, new MyEventArgs {Exception = exception});
}
}
else
{
logger.Warn("Log arrival date time is not less than DateTime.Now+30 minutues");
}
}
else
{
logger.Warn("HubWinClient not connected to send log");
NotConnectedToSentLog(this, new EventArgs());
}
}
/// <summary>
/// when Hub receives log from HubWinClient, calls this method to inform send success
/// </summary>
/// <param name="log"></param>
public void LogSentToWeb(int logId)
{
logger.Debug("Call back from Hub: send success");
LogSentToHub(this, logId);
}
}
Here is my test:
[Category("Integration")]
public class HubWinClientTests
{
[Test]
public void TestConnection()
{
//arrange
const int port = 4000;
HubHost hubHost = new HubHost(port);
HubWinClient hubWinClient = new HubWinClient(port,"mvc app client");
bool clientConnected = false;
bool clientDisconnected = false;
bool hubInvokeError = false;
hubWinClient.ConnectedToHub += (sender, args) => { clientConnected = true; };
hubWinClient.DisonnectedFromHub += (sender, args) => { clientDisconnected = true; };
hubWinClient.HubInvokeError += (sender, args) => { hubInvokeError = true; };
//act
hubHost.Start();
hubWinClient.Start();
//assert
var constrain = Is.True.After(10000, 100);
Assert.That(() => clientConnected, constrain);
//act
hubWinClient.SendToHub(new LogMessage());
//assert
var constrain2 = Is.True.After(2000, 100);
Assert.That(() => hubInvokeError == false, constrain2);
// act
hubWinClient.DisconnectFromHub();
// assert
var constrain1 = Is.True.After(2000, 100);
Assert.That(() => clientDisconnected, constrain1);
hubHost.Stop();
}
}
For some reason when i run my the test by resharper nunit runner, hub instance does created and my test fails. i think it's related to Resharper's and how it create test environment (i'e process creation and such stuff).
Any ideas.
Thanks.
i'm developing an app, and i need to play music from url.
i'm using this code, and it works fine.
But, while a song is playing, and the screen switches off, then the music stops. I need that the music continues playing until its end, even if the screen switches off.
i suppose i have to change this file, but i don't know how:
using System;
using AudioToolbox;
using System.Threading;
using System.Collections.Generic;
using System.Linq;
namespace SecondoSenso
{
/// <summary>
/// A Class to hold the AudioBuffer with all setting together
/// </summary>
internal class AudioBuffer
{
public IntPtr Buffer { get; set; }
public List<AudioStreamPacketDescription> PacketDescriptions { get; set; }
public int CurrentOffset { get; set; }
public bool IsInUse { get; set; }
}
/// <summary>
/// Wrapper around OutputQueue and AudioFileStream to allow streaming of various filetypes
/// </summary>
public class StreamingPlayback : IDisposable
{
public bool boolDispose = false;
public event EventHandler Finished;
public event Action<OutputAudioQueue> OutputReady;
// the AudioToolbox decoder
AudioFileStream fileStream;
int bufferSize = 128 * 256;
List<AudioBuffer> outputBuffers;
AudioBuffer currentBuffer;
// Maximum buffers
int maxBufferCount = 4;
// Keep track of all queued up buffers, so that we know that the playback finished
int queuedBufferCount = 0;
// Current Filestream Position - if we don't keep track we don't know when to push the last uncompleted buffer
long currentByteCount = 0;
//Used to trigger a dump of the last buffer.
bool lastPacket;
public OutputAudioQueue OutputQueue;
public bool Started { get; private set; }
public float Volume {
get {
return OutputQueue.Volume;
}
set {
OutputQueue.Volume = value;
}
}
/// <summary>
/// Defines the size forearch buffer, when using a slow source use more buffers with lower buffersizes
/// </summary>
public int BufferSize {
get {
return bufferSize;
}
set {
bufferSize = value;
}
}
/// <summary>
/// Defines the maximum Number of Buffers to use, the count can only change after Reset is called or the
/// StreamingPlayback is freshly instantiated
/// </summary>
public int MaxBufferCount {
get {
return maxBufferCount;
}
set {
maxBufferCount = value;
}
}
public StreamingPlayback () : this (AudioFileType.MP3)
{
}
public StreamingPlayback (AudioFileType type)
{
fileStream = new AudioFileStream (type);
fileStream.PacketDecoded += AudioPacketDecoded;
fileStream.PropertyFound += AudioPropertyFound;
}
public void Reset ()
{
if (fileStream != null) {
fileStream.Close ();
fileStream = new AudioFileStream (AudioFileType.MP3);
currentByteCount = 0;
fileStream.PacketDecoded += AudioPacketDecoded;
fileStream.PropertyFound += AudioPropertyFound;
}
}
public void ResetOutputQueue ()
{
if (OutputQueue != null) {
OutputQueue.Stop (true);
OutputQueue.Reset ();
foreach (AudioBuffer buf in outputBuffers) {
buf.PacketDescriptions.Clear ();
OutputQueue.FreeBuffer (buf.Buffer);
}
outputBuffers = null;
OutputQueue.Dispose ();
}
}
/// <summary>
/// Stops the OutputQueue
/// </summary>
public void Pause ()
{
OutputQueue.Pause ();
Started = false;
}
/// <summary>
/// Starts the OutputQueue
/// </summary>
public void Play ()
{
OutputQueue.Start ();
Started = true;
}
/// <summary>
/// Main methode to kick off the streaming, just send the bytes to this method
/// </summary>
public void ParseBytes (byte[] buffer, int count, bool discontinuity, bool lastPacket)
{
this.lastPacket = lastPacket;
fileStream.ParseBytes (buffer, 0, count, discontinuity);
}
public void Dispose ()
{
Dispose (true);
GC.SuppressFinalize (this);
}
public void Dispose(int tt) {
}
/// <summary>
/// Cleaning up all the native Resource
/// </summary>
protected virtual void Dispose (bool disposing)
{
if (disposing) {
if (OutputQueue != null)
OutputQueue.Stop(true);
if (outputBuffers != null) {
foreach (var b in outputBuffers)
OutputQueue.FreeBuffer (b.Buffer);
outputBuffers.Clear ();
outputBuffers = null;
}
if (fileStream != null) {
fileStream.Close ();
fileStream = null;
}
if (OutputQueue != null) {
OutputQueue.Dispose ();
OutputQueue = null;
}
}
}
/// <summary>
/// Saving the decoded Packets to our active Buffer, if the Buffer is full queue it into the OutputQueue
/// and wait until another buffer gets freed up
/// </summary>
void AudioPacketDecoded (object sender, PacketReceivedEventArgs args)
{
foreach (var p in args.PacketDescriptions) {
currentByteCount += p.DataByteSize;
AudioStreamPacketDescription pd = p;
int left = bufferSize - currentBuffer.CurrentOffset;
if (left < pd.DataByteSize) {
EnqueueBuffer ();
WaitForBuffer ();
}
AudioQueue.FillAudioData (currentBuffer.Buffer, currentBuffer.CurrentOffset, args.InputData, (int)pd.StartOffset, pd.DataByteSize);
// Set new offset for this packet
pd.StartOffset = currentBuffer.CurrentOffset;
// Add the packet to our Buffer
currentBuffer.PacketDescriptions.Add (pd);
// Add the Size so that we know how much is in the buffer
currentBuffer.CurrentOffset += pd.DataByteSize;
}
if ((fileStream != null && currentByteCount == fileStream.DataByteCount) || lastPacket)
EnqueueBuffer ();
}
/// <summary>
/// Flush the current buffer and close the whole thing up
/// </summary>
public void FlushAndClose ()
{
if (OutputQueue != null) {
EnqueueBuffer ();
OutputQueue.Flush ();
}
Dispose ();
}
/// <summary>
/// Enqueue the active buffer to the OutputQueue
/// </summary>
void EnqueueBuffer ()
{
currentBuffer.IsInUse = true;
OutputQueue.EnqueueBuffer (currentBuffer.Buffer, currentBuffer.CurrentOffset, currentBuffer.PacketDescriptions.ToArray ());
queuedBufferCount++;
StartQueueIfNeeded ();
}
/// <summary>
/// Wait until a buffer is freed up
/// </summary>
void WaitForBuffer ()
{
int curIndex = outputBuffers.IndexOf (currentBuffer);
currentBuffer = outputBuffers [curIndex < outputBuffers.Count - 1 ? curIndex + 1 : 0];
lock (currentBuffer) {
while (currentBuffer.IsInUse)
Monitor.Wait (currentBuffer);
}
}
void StartQueueIfNeeded ()
{
if (Started)
return;
Play ();
}
/// <summary>
/// When a AudioProperty in the fed packets is found this callback is called
/// </summary>
void AudioPropertyFound (object sender, PropertyFoundEventArgs args)
{
if (args.Property == AudioFileStreamProperty.ReadyToProducePackets) {
Started = false;
if (OutputQueue != null)
OutputQueue.Dispose ();
OutputQueue = new OutputAudioQueue (fileStream.StreamBasicDescription);
if (OutputReady != null)
OutputReady (OutputQueue);
currentByteCount = 0;
OutputQueue.BufferCompleted += HandleBufferCompleted;
outputBuffers = new List<AudioBuffer> ();
for (int i = 0; i < MaxBufferCount; i++) {
IntPtr outBuffer;
OutputQueue.AllocateBuffer (BufferSize, out outBuffer);
outputBuffers.Add (new AudioBuffer () {
Buffer = outBuffer,
PacketDescriptions = new List<AudioStreamPacketDescription> ()
});
}
currentBuffer = outputBuffers.First ();
OutputQueue.MagicCookie = fileStream.MagicCookie;
}
}
/// <summary>
/// Is called when a buffer is completly read and can be freed up
/// </summary>
void HandleBufferCompleted (object sender, BufferCompletedEventArgs e)
{
queuedBufferCount--;
IntPtr buf = e.IntPtrBuffer;
foreach (var buffer in outputBuffers) {
if (buffer.Buffer != buf)
continue;
// free Buffer
buffer.PacketDescriptions.Clear ();
buffer.CurrentOffset = 0;
lock (buffer) {
buffer.IsInUse = false;
Monitor.Pulse (buffer);
}
}
if (queuedBufferCount == 0 && Finished != null)
Finished (this, new EventArgs ());
}
}
}
how can i change the code to allow that?
thanks in advance for helps.
Put this following code in your AppDelegate.csin the FinishedLaunchingmethod.
NSError sessionError = null;
AVAudioSession.SharedInstance().SetCategory(AVAudioSession.CategoryAmbient, out sessionError);
AVAudioSession.SharedInstance().SetActive(true, out sessionError);
Apps get suspended when the phone is put to sleep. If you wan't your app to continue executing, you have to register for background execution.
Here is a nice guide Jonathan Sagorin (if you don't mind putting it over from Swift/obj-c).
Basically the class you are looking for is AVAudioSession and it's SetActive Method to activate a background audio session.
I have a process (Task) that works with a Tree (C#). That tree is loaded from a postgre database. That process is listening to events. When an event occurs, the Tree is updated.
With another process (Task), I use the same Tree, to reflect the changes in a Treeview using a Timer.
It's very slow. So there is something that I'm doing wrong...
I need help to know what is the best approach to do this, information about books, examples of Thread, BackgroundWorker, Timer, Task, Real Time Systems, and so on.
Thanks!
Regards.
This is an example similar to the code I am developing...There are 3 Classes: A, B and C. A is the "master" class. It has a list of B objects and a List of B Threads. Each B Object has a list of C Classes and C Threads.
C class is ready when an operation is done (in the example, put the variable "cIsReady" to true. When all the cObjects in the list, of object B, are ready, then "bIsReady" is set to true. When all the bObjects in the List, of object A, are ready, then "aIsReady" is set to true.
public class A
{
private List<B> bList;
private List<Thread> threadBList;
private bool aIsReady;
/// <summary>
/// List of classes managed by A Class.
/// </summary>
public List<B> BList
{
get
{
return bList;
}
set
{
bList = value;
}
}
/// <summary>
/// List of Threads. Each Thread manages a B Class.
/// </summary>
public List<Thread> ThreadBList
{
get
{
return threadBList;
}
set
{
threadBList = value;
}
}
/// <summary>
/// Indicates when A is ready.
/// </summary>
public bool AIsReady
{
get
{
return aIsReady;
}
set
{
aIsReady = value;
}
}
/// <summary>
/// Constructor.
/// </summary>
public A()
{
}
/// <summary>
/// Starts the A Class.
/// </summary>
public void startA()
{
this.bList = new List<B>();
this.threadBList = new List<Thread>();
// for example
int numberOfBClasses = 3;
for (int i = 0; i < numberOfBClasses; ++i)
{
B bObject = new B();
this.bList.Add(bObject);
Thread bThread = new Thread(bObject.startB);
bThread.IsBackground = true;
this.threadBList.Add(bThread);
} // for (int i = 0; i < numberOfBClasses; ++i)
// Start all the B Threads.
for (int i = 0; i < numberOfBClasses; ++i)
{
this.threadBList[i].Start();
} // for (int i = 0; i < numberOfBClasses; ++i)
while (!aIsReady)
{
foreach (B bObject in this.bList)
{
if (bObject.BIsReady)
{
this.aIsReady = true;
} // if (bObject.BIsReady)
else
{
this.aIsReady = false;
} // else [ if (bObject.BIsReady) ]
} // foreach (B bObject in this.bList)
} // while (!aIsReady)
this.aIsReady = true;
}
} // public class A
public class B
{
private List<C> cList;
private List<Thread> threadCList;
private bool bIsReady;
/// <summary>
/// List of classes managed by B Class.
/// </summary>
public List<C> CList
{
get
{
return cList;
}
set
{
cList = value;
}
}
/// <summary>
/// List of Threads. Each Thread manages a C Class.
/// </summary>
public List<Thread> ThreadCList
{
get
{
return threadCList;
}
set
{
threadCList = value;
}
}
/// <summary>
/// Indicates when B is ready.
/// </summary>
public bool BIsReady
{
get
{
return bIsReady;
}
set
{
bIsReady = value;
}
}
/// <summary>
/// Constructor
/// </summary>
public B()
{
}
/// <summary>
/// Start B
/// </summary>
public void startB()
{
this.cList = new List<C>();
this.threadCList = new List<Thread>();
// for example
int numberOfCClasses = 5;
for (int i = 0; i < numberOfCClasses; ++i)
{
C cObject = new C();
this.cList.Add(cObject);
Thread cThread = new Thread(cObject.startC);
cThread.IsBackground = true;
this.threadCList.Add(cThread);
} // for (int i = 0; i < numberOfCClasses; ++i)
// Start all the C Threads.
for (int i = 0; i < numberOfCClasses; ++i)
{
this.threadCList[i].Start();
} // for (int i = 0; i < numberOfCClasses; ++i)
while (!bIsReady)
{
foreach (C cObject in this.cList)
{
if (cObject.CIsReady)
{
this.bIsReady = true;
} // if (cObject.CIsReady)
else
{
this.bIsReady = false;
} // else [ if (cObject.CIsReady) ]
} // foreach (C in this.cList)
} // while (!bIsReady)
this.bIsReady = true;
}
} // public class B
public class C
{
private bool cIsReady;
/// <summary>
/// Indicates that the object is ready.
/// </summary>
public bool CIsReady
{
get
{
return cIsReady;
}
set
{
cIsReady = value;
}
}
/// <summary>
/// Constructor.
/// </summary>
public C()
{
}
/// <summary>
/// Starts C.
/// </summary>
public void startC()
{
this.cIsReady = true;
}
} // public class C
So, when I put the following code under, a form load event for example:
A aObject = new A();
Thread aThread = new Thread(aObject.startA);
while (!aObject.AIsReady)
{
Thread.Sleep(100);
}
MessageBox.Show("A is Ready");
The aObject never is ready...
Thanks!
I have a producer/consumer queue as following but I am getting ArgumentWException.
Following is the code:
public class ProducerConsumer<T> where T : class
{
#region Private Variables
private Thread _workerThread;
private readonly Queue<T> _workQueue;
private object _enqueueItemLocker = new object();
private object _processRecordLocker = new object();
private readonly Action<T> _workCallbackAction;
private AutoResetEvent _workerWaitSignal;
#endregion
#region Constructor
public ProducerConsumer(Action<T> action)
{
_workQueue = new Queue<T>();
_workCallbackAction = action;
}
#endregion
#region Private Methods
private void ProcessRecord()
{
while (true)
{
T workItemToBeProcessed = default(T);
bool hasSomeWorkItem = false;
lock (_processRecordLocker)
{
hasSomeWorkItem = _workQueue.Count > 0;
if (hasSomeWorkItem)
{
workItemToBeProcessed = _workQueue.Dequeue();
if (workItemToBeProcessed == null)
{
return;
}
}
}
if (hasSomeWorkItem)
{
if (_workCallbackAction != null)
{
_workCallbackAction(workItemToBeProcessed);
}
}
else
{
_workerWaitSignal.WaitOne();
}
}
}
#endregion
#region Public Methods
/// <summary>
/// Enqueues work item in the queue.
/// </summary>
/// <param name="workItem">The work item.</param>
public void EnQueueWorkItem(T workItem)
{
lock (_enqueueItemLocker)
{
_workQueue.Enqueue(workItem);
if (_workerWaitSignal == null)
{
_workerWaitSignal = new AutoResetEvent(false);
}
_workerWaitSignal.Set();
}
}
/// <summary>
/// Stops the processer, releases wait handles.
/// </summary>
/// <param name="stopSignal">The stop signal.</param>
public void StopProcesser(AutoResetEvent stopSignal)
{
EnQueueWorkItem(null);
_workerThread.Join();
_workerWaitSignal.Close();
_workerWaitSignal = null;
if (stopSignal != null)
{
stopSignal.Set();
}
}
/// <summary>
/// Starts the processer, starts a new worker thread.
/// </summary>
public void StartProcesser()
{
if (_workerWaitSignal == null)
{
_workerWaitSignal = new AutoResetEvent(false);
}
_workerThread = new Thread(ProcessRecord) { IsBackground = true };
_workerThread.Start();
}
#endregion
}
Another class is:
public class Tester
{
private readonly ProducerConsumer<byte[]> _proConsumer;
public Tester()
{
_proConsumer = new ProducerConsumer<byte[]>(Display);
}
public void AddData(byte[] data)
{
try
{
_proConsumer.EnQueueWorkItem(recordData);
}
catch (NullReferenceException nre)
{
}
}
public void Start()
{
_proConsumer.StartProcesser();
}
private static object _recordLocker = new object();
private void Display(byte[] recordByteStream)
{
try
{
lock (_recordLocker)
{
Console.WriteLine("Done with data:" + BitConverter.ToInt32(recordByteStream, 0));
}
}
catch (Exception ex)
{
}
}
}
And my main function:
class Program
{
private static Tester _recorder;
static void Main(string[] args)
{
_recorder = new Tester();
_recorder.StartRecording();
for (int i = 0; i < 100000; i++)
{
_recorder.AddRecordData(BitConverter.GetBytes(i));
}
Console.Read();
}
}
Any idea why do I get the exception and what should I do to avoid that ?
Your class, in its current implementation, is not thread-safe. You're using two different objects for your Enqueue (lock (_enqueueItemLocker)) and Dequeue (lock (_processRecordLocker)) calls, which creates a race condition in your Queue<T>.
You need to lock the same object instance on both calls in order to safely use the queue.
If you're using .NET 4, I'd recommend either using ConcurrentQueue<T> or BlockingCollection<T> instead, as these would eliminate the need for the locks in your code, since they're thread-safe.