I am using TelegramBotClient component in my project. Unfortunately the component
does not suggest any Dispose() method.
In my project I need to renew the object based on the token provided:
public TelegramBotClient NewClient(string token)
{
return new TelegramBotClient(token);
}
I need to dispose the object created
NewClient(token).SendTextMessageAsync(message.Chat.Id, message.Text, replyMarkup: keyboard, parseMode: Telegram.Bot.Types.Enums.ParseMode.Html);
How can I properly dispose the object?
If the third party-class implements IDisposable interface, then you can create object of that class with using block. This way the object disposal will be taken care by the framework.
If the class does not implements IDisposable that means that the class does not use any unmanaged resources and the author of the class does not see any possibility of memory leak caused by this class object if it not disposed intentionally.
If you still want to make sure that the third-party class object release the resources as soon at its usage is over, you can do that manually by wrapping it in your own class which implement IDisposable.
public class TextMessageClient : IDisposable
{
bool disposed = false;
private Telegram.Bot.TelegramBotClient client;
public TextMessageClient()
{
//Write your own logic to get the token
//Or accept the token as an argument of constructor.
var token = Guid.NewGuid().ToString();
client = new Telegram.Bot.TelegramBotClient(token);
}
public TextMessageClient(string token)
{
client = new Telegram.Bot.TelegramBotClient(token);
}
public async Task<Telegram.Bot.Types.Message> SendMessageAsync(string chatId, string message, string, IReplyMarkup keyboard, )
{
return await client.SendMessageAsync(chatId, message, replyMarkup: keyboard, parseMode: Telegram.Bot.Types.Enums.ParseMode.Html);
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
client = null;
}
disposed = true;
}
}
Now you can use this class as following.
using(var messageClient = new TextMessageClient())
{
var message = await messageClient.SendMessageAsync(<somechatid>, <somemessage>, <somerelaymarkup>);
}
I hope this will help you resolve your issue.
Related
I have the following method in the aspx file (.NET Framework 4.6.2 project):
public static string SetAvgPeriodDays(int userId)
{
var service = new AveragePeriodDaysService(EfHelper.GetContext());
try
{
return service.SetAveragePeriodDays(userId);
}
catch (Exception e)
{
return e.Message;
}
}
AveragePeriodDaysService class has a constructor that accepts DbContext instance:
public class AveragePeriodDaysService
{
private readonly MyDbContext _ctx;
public AveragePeriodDaysService(MyDbContext ctx)
{
_ctx = ctx;
}
public string SetAveragePeriodDays(int userId)
{
// main logic goes here...
}
}
And here EfHelper class:
public class EfHelper
{
public static MyDbContext GetContext()
{
var options = new DbContextOptionsBuilder<MyDbContext>();
var connectionString = ...
options.UseSqlServer(connectionString);
options.UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);
return new MyDbContext(options.Options);
}
}
Question. Should I dispose MyDbContext? If yes, how should I do it properly?
As a rule you should never dispose dependencies that you got from outside because you never know who else uses same instance of this dependency. It means AveragePeriodDaysService can't dispose MyDbContext. But SetAvgPeriodDays knows exactly who will consume MyDbContext because it requested the creation of MyDbContext, hence it can and should dispose it after usage. Use using keyword:
public static string SetAvgPeriodDays(int userId)
{
using(var ctx = EfHelper.GetContext())
{
var service = new AveragePeriodDaysService(ctx);
try
{
return service.SetAveragePeriodDays(userId);
}
catch (Exception e)
{
return e.Message;
}
}
}
I'm actually not so sure what the correct patterns for this are, but I normally go with the following approach (something like the .NET Stream or SafeHandle classes do):
Your AveragePeriodDaysService really seems to take control of the context (it stores it in a private readonly field). So actually this class should implement IDisposable and dispose of the context itself.
On the other hand, you might want to use a single context for different "service" classes without always creating a new one. So it would be annoying if these classes always dispose the context.
So my way of implementing it would be something like this:
public class AveragePeriodDaysService : IDisposable
{
private readonly MyDbContext _ctx;
private readonly bool _ownContext;
public AveragePeriodDaysService(MyDbContext ctx, bool ownContext)
{
_ctx = ctx;
_ownContext = ownContext;
}
protected virtual void Dispose(bool disposing)
{
if (disposing) GC.SuppressFinalize(this);
if (_ownContext) _ctx.Dispose();
}
public void Dispose()
{
Dispose(true);
}
Then you can decide if the created instance should be responsible for disposing the context or if the creator needs to keep control.
Of course, if the created instance should take control, you need to properly dispose of this instance.
I am currently trying to override the Remove function of the generic List-Class. But I am struggling with one tiny part of my approach - with the reference to an object outside of the Remove-method.
public new void Remove(ref string item)
{
if (Count > 9)
{
Remove(this[0]);
}
base.Remove(item);
}
This method doesnt work because it is not overriding the actual Remove-method.
Does anyone know how to handle this?
EDIT: in the remove function I want to call a method on the reference object.
EDIT2: my current version
class SocketList<WebSocketConnection>
{
private List<WebSocketConnection> theList = new List<WebSocketConnection>();
public void Remove(ref WebSocketConnection obj)
{
obj.Dispose();
theList.Remove(obj);
// additional stuff
}
}
But in this version it is not possible to call the Dispose method on the referenced object. Im getting a message that says that there is no such method available for this object.
EDIT3: This is the Class in which I want to call the Dispose method
public class WebSocketConnection : IWebSocketConnection
{
{...}
// Flag: Has Dispose already been called?
private bool disposed = false;
// Instantiate a SafeHandle instance.
private SafeHandle handle = new SafeFileHandle(IntPtr.Zero, true);
{...}
// Public implementation of Dispose pattern callable by consumers.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
// Protected implementation of Dispose pattern.
protected virtual void Dispose(bool disposing)
{
if (disposed)
return;
if (disposing)
{
handle.Dispose();
// Free any other managed objects here.
//
}
// Free any unmanaged objects here.
//
disposed = true;
}
}
You can´t override any member of List<T> because non of them is virtual. Also new won´t solve this because it simply hides the base-implementation. You may your list as MyExtList<MyClass> a = new MyExtList<MyClass>(). However whenever you cast this instance to its base-class also the base-implementation is used instead of your "overridden" one.
However you can do the following to achieve what you really want:
class MyExtList<T>
{
private List<T> theList = new List<T>();
public void Remove(T obj)
{
theList.Remove(obj)
// additional stuff
}
}
Thuse you won´t even need inheritance of List<T> but use a compoisition which gives you much more flexibility on what you offer to the user of your class. With your current implementation the user could do everything with the list what he could do with the generic List-implementation also. However in most situation you´re just interested in providing a few methods instead of all. So you can nicely hide everything you won´t provide to the outside by making a completely new class that uses List<T> instead of deriving from it.
Is correct that a public method calls the Dispose of IDisposable in the same class?
E.g.
public class Worker : IDisposable
{
public void Close()
{
SendCloseCommand();
Dispose();
}
public void Dispose()
{
////other resources release
}
private void SendCloseCommand()
{
}
}
Another thing about disposable pattern:
If the Close should be always called, is better that is called from the Dispose method or not?
If not, I should put the usage of the Worker class in a try/catch/finally everywhere, to call the Close. Right?
The correct design should instead be?
public class Worker : IDisposable
{
public void Close()
{
SendCloseCommand();
}
public void Dispose()
{
Close();
////other resources release
}
private void SendCloseCommand()
{
////other stuff
}
}
If you look at Microsoft implementation for StreamReader, Dispose gets called from Close,
public override void Close()
{
Dispose(true);
}
and also the implementation for Dispose closes the stream as well by calling Close of base Stream.
protected override void Dispose(bool disposing)
{
// Dispose of our resources if this StreamReader is closable.
// Note that Console.In should be left open.
try {
// Note that Stream.Close() can potentially throw here. So we need to
// ensure cleaning up internal resources, inside the finally block.
if (!LeaveOpen && disposing && (stream != null))
stream.Close();
}
finally {
if (!LeaveOpen && (stream != null)) {
stream = null;
encoding = null;
decoder = null;
byteBuffer = null;
charBuffer = null;
charPos = 0;
charLen = 0;
base.Dispose(disposing);
}
}
}
In your class implementation, I would call the Dispose from your Close method as you are doing in your first code snippet. In Dispose, I would check for Worker status, if it is not closed then close it using SendCloseCommand, and then release resources.
public void Dispose()
{
if(this.Status != Closed) // check if it is not already closed
{
SendCloseCommand();
}
////other resources release
}
This will ensure your resources disposal, even if your class is used with using statement, or if any one calls Close manually.
Just remember to check status of your Worker object, before issuing Close Command.
Microsoft has some suggestions about having a Close method on a class implementing IDisposable. It is part of the Dispose Pattern guidelines:
CONSIDER providing method Close(), in addition to the Dispose(), if close is standard terminology in the area.
When doing so, it is important that you make the Close implementation identical to Dispose and consider implementing the IDisposable.Dispose method explicitly.
public class Stream : IDisposable {
IDisposable.Dispose(){
Close();
}
public void Close(){
Dispose(true);
GC.SuppressFinalize(this);
}
}
So Microsofts suggestion is to hide Dispose and let it call Close to do the actual cleanup. Also, remember the guideline about multiple calls to Dispose:
DO allow the Dispose(bool) method to be called more than once. The method might choose to do nothing after the first call.
Following these guidelines makes your code consistent with the .NET library and you will avoid any confusion about if your class should be closed or disposed for proper cleanup.
I'm creating a .NET API and one of my methods returns a Stream. I need to ensure that some other class is disposed when the caller disposes the Stream that I return.
The only way I can think to do this is to create a wrapper class that inherits from Stream and tacks on the functionality I need, delegating everything else to the underlying Stream.
I don't like having to decorate a framework class simply because it may get new members in future .NET releases that I would need to update my API to support.
Is there a better way to do this?
Example
Here is a concrete example for your pondering.
Keep in mind that one of the requirements of this class is that it cannot require disposal, referring to the ContentSource class in the example.
public class ContentSource
{
public Stream OpenRead()
{
var entry = GetEntry();
// TODO: Ensure that when the stream we return is disposed, we also dispose of `entry.Archive`.
return entry.Open();
}
private ZipArchiveEntry GetEntry()
{
ZipArchive archive = null;
try
{
archive = new ZipArchive(_zipContent.OpenRead(), ZipArchiveMode.Read, false);
var entry = archive.GetEntry(_entryName);
if (entry == null)
{
throw new InvalidOperationException("Specified entry was not found in the ZIP archive. " + _entryName);
}
return entry;
}
finally
{
if (archive != null)
{
archive.Dispose();
}
}
}
}
Stream Wrapper Example
This is the solution I can think of that I'm not happy with.
public sealed class DependencyDisposingStreamWrapper : Stream
{
private readonly Stream _stream;
private readonly IDisposable _dependency;
private bool _disposed;
public DependencyDisposingStreamWrapper(Stream stream, IDisposable dependency)
{
_stream = stream;
_dependency = dependency;
}
# region - Overrides of all Stream members, delegating to underlying stream -
// ...
#endregion
protected override void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_dependency.Dispose();
}
base.Dispose(disposing);
_disposed = true;
}
}
}
Composition instead of inheritance?
That's how the .Net does it for items like, say, StreamReader. There's a member property for the base stream, rather than inheriting from stream.
If want to work with the existing types like StreamReader/Writer, TCPClient, etc, you'll be stuck inheriting Stream, though.
You will need to create a wrapper. There is no means of being notified when the stream is disposed. Some other types may provide a public event that is fired when they are disposed, but Stream doesn't.
I have problem with increasing memory. I use MEF in caliburn.micro on creation new screen - WPF window.
View model of screen/view look like this:
[Export(typeof(IChatViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class ChatViewModel : Screen, IChatViewModel
{}
On creation I use ExportFactory, controler is here:
public interface IViewModelsControler
{
ExportLifetimeContext<IChatViewModel> CreatChatViewModel();
}
[Export(typeof(IViewModelsControler))]
public class ViewModelsControler : IViewModelsControler
{
[Import]
public ExportFactory<IChatViewModel> ChatViewFactory { get; set; }
public ExportLifetimeContext<IChatViewModel> CreatChatViewModel()
{
return ChatViewFactory.CreateExport();
}
}
I use ViewModelsControler class in ChatScreenManager class. This class Open/Remove chat screen.
Here is it:
[Export(typeof(IChatScreenManager))]
public class ChatScreenManager : IChatScreenManager
{
private IWindowManager _windowManager;
[Import]
public IViewModelsControler ViewModelControler { get; set; }
[ImportingConstructor]
public ChatScreenManager(IWindowManager windowManager)
{
_windowManager = windowManager;
ActiveChatScreens = new Dictionary<string, ExportLifetimeContext<IChatViewModel>>();
}
//store active screen
public Dictionary<string, ExportLifetimeContext<IChatViewModel>> ActiveChatScreens { get; set; }
public void OpenChatScreen(DetailData oponent, string avatarNick, BitmapImage avatarImage)
{
if (!ActiveChatScreens.ContainsKey(oponent.Info.Nick))
{
//create new chat screen with view model controler
ExportLifetimeContext<IChatViewModel> chatScreen = ViewModelControler.CreatChatViewModel();
//show
_windowManager.Show(chatScreen.Value);
//add ref to the dic
ActiveChatScreens.Add(oponent.Info.Nick, chatScreen);
}
}
public void RemoveChatScreen(string clossingScreen)
{
MessageBox.Show(GC.GetTotalMemory(true).ToString());
ActiveChatScreens[clossingScreen].Dispose();
ActiveChatScreens.Remove(clossingScreen);
GC.Collect();
GC.SuppressFinalize(this);
MessageBox.Show(GC.GetTotalMemory(true).ToString());
}
}
And my problem is:
I call OpneChatScreen method from ChatScreenManager it open new WPF window
Add reference on this window to the dictionary.
When I am closing window I call RemoveChatScreen.
In RemoveChaScreen:
I get total memory, for example is it 37,000K
Then I call Dipose method on ExportLifetimeContext chatScreen
Force GC
And get total memory, for example is it 39,000K
Memory usage is stil increasing. I hope if I call Dispose method on object ChatViewModel and also ChatView object these object are destroyed.
Do not force GC! Also, the Dispose() method should follow removal from your collection.
public void RemoveChatScreen(string closingScreen)
{
MessageBox.Show(GC.GetTotalMemory(true).ToString());
IChatViewModel chatWindow = ActiveChatScreens[closingScreen]
// remove from collection - GC may pass over object referenced in collection
// until next pass, or 3rd pass...who knows, it's indeterminate
ActiveChatScreens.Remove(closingScreen);
// all clean up should be performed within Dispose method
chatWindow.Dispose();
//GC.Collect();
//GC.SuppressFinalize(this);
MessageBox.Show(GC.GetTotalMemory(true).ToString());
}
Forcing garbage collection is not recommended. There are ways to work with GC, however, and that is typically done in the Dispose() method of the disposable class. Your derived ChatView object should be defined something like:
class ChatView : IChatViewModel, IDisposable
{ }
ChatView requires a Dispose() method be implemented. There is a pattern to follow (from MSDN) when creating disposable classes:
// Design pattern for a base class.
public class ChatView : IChatViewModel, IDisposable
{
private bool disposed = false;
//Implement IDisposable.
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!disposed)
{
if (disposing)
{
// Free other state (managed objects).
}
// Free your own state (unmanaged objects).
// Set large fields to null.
disposed = true;
}
}
// Use C# destructor syntax for finalization code.
~ChatView()
{
// Simply call Dispose(false).
Dispose (false);
}
}