Calling
http://foo/home/cachetest
for
[UrlRoute(Path = "home/cachetest")]
[OutputCache(Duration = 10, VaryByParam = "none")]
public ActionResult CacheTest()
{
return Content(DateTime.Now.ToString());
}
will show the same content for every 10 seconds no matter how often i refresh page.
Is it possible to easily add sliding expiration so it would NOT change after 10 seconds in case i have refreshed the page?
You could create a custom cache filter instead of default OutputCache one. Like this below, note the sliding expiration could be set here. Caveat in that I have not used this for sliding expiration, but works well for other things.
public class CacheFilterAttribute : ActionFilterAttribute
{
private const int Second = 1;
private const int Minute = 60 * Second;
private const int Hour = 60 * Minute;
public const int SecondsInDay = Hour * 24;
/// <summary>
/// Gets or sets the cache duration in seconds.
/// The default is 10 seconds.
/// </summary>
/// <value>The cache duration in seconds.</value>
public int Duration
{
get;
set;
}
public int DurationInDays
{
get { return Duration / SecondsInDay; }
set { Duration = value * SecondsInDay; }
}
public CacheFilterAttribute()
{
Duration = 10;
}
public override void OnActionExecuted(
ActionExecutedContext filterContext)
{
if (Duration <= 0) return;
HttpCachePolicyBase cache =
filterContext.HttpContext.Response.Cache;
TimeSpan cacheDuration = TimeSpan.FromSeconds(Duration);
cache.SetCacheability(HttpCacheability.Public);
cache.SetExpires(DateTime.Now.Add(cacheDuration));
cache.SetMaxAge(cacheDuration);
cache.SetSlidingExpiration(true);
cache.AppendCacheExtension("must-revalidate, proxy-revalidate");
}
}
Been reading the source for the OutputCacheAttribute and I don't think there's an easy way to do this.
You're most likely going to need to create your own solution.
You can't. Internal timer of Cache class spins every 20 secs. I suggest you to try PCache class under PokeIn library. You can set down to 6 secs on it. Also, PCache far more faster in comparison to .NET cache class.
Related
I would like to set a Timer in Event time that fires based on the smallest timestamp seen in the elements within my DoFn.
For performance reasons the Timer API does not support a read() operation, which for the vast majority of use cases is not a required feature. In the small set of use cases where it is needed, for example when you need to set a Timer in EventTime based on the smallest timestamp seen in the elements within a DoFn, we can make use of a State object to keep track of the value.
Java (SDK 2.10.0)
// In this pattern, a Timer is set to fire based on the lowest timestamp seen in the DoFn.
public class SetEventTimeTimerBasedOnEarliestElementTime {
private static final Logger LOG = LoggerFactory
.getLogger(SetEventTimeTimerBasedOnEarliestElementTime.class);
public static void main(String[] args) {
// Create pipeline
PipelineOptions options = PipelineOptionsFactory.
fromArgs(args).withValidation().as(PipelineOptions.class);
// We will start our timer at a fixed point
Instant now = Instant.parse("2000-01-01T00:00:00Z");
// ----- Create some dummy data
// Create 3 elements, incrementing by 1 minute
TimestampedValue<KV<String, Integer>> time_1 = TimestampedValue.of(KV.of("Key_A", 1), now);
TimestampedValue<KV<String, Integer>> time_2 = TimestampedValue
.of(KV.of("Key_A", 2), now.plus(Duration.standardMinutes(1)));
TimestampedValue<KV<String, Integer>> time_3 = TimestampedValue
.of(KV.of("Key_A", 3), now.plus(Duration.standardMinutes(2)));
Pipeline p = Pipeline.create(options);
// Apply a fixed window of duration 10 min and Sum the results
p.apply(Create.timestamped(time_3, time_2, time_1)).apply(
Window.<KV<String, Integer>>into(FixedWindows.<Integer>of(Duration.standardMinutes(10))))
.apply(ParDo.of(new StatefulDoFnThatSetTimerBasedOnSmallestTimeStamp()));
p.run();
}
/**
* Set timer to the lowest value that we see in the stateful DoFn
*/
public static class StatefulDoFnThatSetTimerBasedOnSmallestTimeStamp
extends DoFn<KV<String, Integer>, KV<String, Integer>> {
// Due to performance considerations there is no read on a timer object.
// We make use of this Long value to keep track.
#StateId("currentTimerValue") private final StateSpec<ValueState<Long>> currentTimerValue =
StateSpecs.value(BigEndianLongCoder.of());
#TimerId("timer") private final TimerSpec timer = TimerSpecs.timer(TimeDomain.EVENT_TIME);
#ProcessElement public void process(ProcessContext c,
#StateId("currentTimerValue") ValueState<Long> currentTimerValue,
#TimerId("timer") Timer timer) {
Instant timeStampWeWantToSet = c.timestamp();
//*********** Set Timer
// If the timer has never been set then we set it.
// If the timer has been set but is larger than our current value then we set it.
if (currentTimerValue.read() == null || timeStampWeWantToSet.getMillis() < currentTimerValue
.read()) {
timer.set(timeStampWeWantToSet);
currentTimerValue.write(timeStampWeWantToSet.getMillis());
}
}
#OnTimer("timer") public void onMinTimer(OnTimerContext otc,
#StateId("currentTimerValue") ValueState<Long> currentTimerValue,
#TimerId("timer") Timer timer) {
// Reset the currentTimerValue
currentTimerValue.clear();
LOG.info("Timer # {} fired", otc.timestamp());
}
}
}
In Dropwizard there is something like meter:
https://metrics.dropwizard.io/3.1.0/getting-started/#meters
It lets me measure rate of events just by invoking mark() method on the metric.
How can I do that in Micrometer?
I can use timers, but I don't want to pass Timer.Sample object to wherever place where I need to call stop() method.
The other missing thing in Micrometer comparing to Dropwizard is a metric that can contain a text message, like gauge in Dropwizard.
Micrometer leverages the strengths of modern metrics backends. So the specific answer to your question depends on which you are using. Take Prometheus for example. The backend can calculate the rate for you.
If you are measuring the rate of how often something is happening you can determine that using a Counter. Take the logback_events_total counter as an example. It is merely counting the number for log messages written.
When alerting or graphing you can then write a query like rate(logback_events_total[1m]) and you will be able to see the rate at which logs have been writen at the 1m rate. You have the ability to change to window from 1m, to 5m or 1h without changing the code.
Regarding text based metrics, those aren't useful for alerting (but can be useful when using a join clause). The typical solution in that case is to create a gauge with a value of 1 or 0 and make your text value a tag. For example:
registry.gaugle('app.info', Tags.of("version","1.0.beta3", this, () -> 1.0));
We had the same problem. In DropWizard we were able to use meters to get the rate of events per minute, but in Micrometer we could not find a built-in way that worked for us.
We needed rates for counters and percentiles for timers. The PrometheusMeterRegistry gave us percentiles, but no rates.
So we built our own Gauge that tracks a Counter. Every time getValue() is called, it fetches the value from the counter and adds it to the right bucket with the current timestamp. Then from all available measurements it can compute the rate over the last minute.
It looks like this:
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import java.util.LinkedList;
import java.util.function.Supplier;
public class OneMinuteRateGauge {
private static final int WINDOW_SECONDS = 60;
private final Supplier<Double> valueSupplier;
private final LinkedList<Bucket> buckets;
private final Clock clock;
public OneMinuteRateGauge(String name, Supplier<Double> valueSupplier, MeterRegistry meterRegistry) {
this(name, valueSupplier, meterRegistry, Clock.SYSTEM);
}
public OneMinuteRateGauge(String name, Supplier<Double> valueSupplier, MeterRegistry meterRegistry, Clock clock) {
this.valueSupplier = valueSupplier;
this.buckets = new LinkedList<>();
Gauge.builder(name, this::getValue).register(meterRegistry);
this.clock = clock;
// Collect one measurement so we have a faster start
getValue();
}
public synchronized double getValue() {
// Update the last bucket or create a new one
long now_millis = clock.monotonicTime() / 1_000_000;
long now_seconds = now_millis / 1_000;
short millis = (short) (now_millis - (now_seconds * 1000));
double value = valueSupplier.get();
if (buckets.size() != 0 && buckets.getLast().getSeconds() == now_seconds) {
buckets.getLast().updateValue(millis, value);
} else {
buckets.addLast(new Bucket(now_seconds, millis, value));
}
// Delete all buckets outside the window except one
while (2 < buckets.size() && buckets.get(1).getSeconds() + WINDOW_SECONDS < now_seconds) {
buckets.pollFirst();
}
if (buckets.size() == 1) {
// Not enough data
return 0;
} else if (now_seconds <= buckets.getFirst().getSeconds() + WINDOW_SECONDS) {
// First bucket is inside the window
return buckets.getLast().getValue() - buckets.getFirst().getValue();
} else {
// Find the weighted average between the first two points
Bucket p0 = buckets.get(0);
Bucket p1 = buckets.get(1);
double px = now_millis - (WINDOW_SECONDS * 1000);
double m = (p1.getValue() - p0.getValue()) / (p1.getTimestampInMillis() - p0.getTimestampInMillis());
double py = m * (px - p0.getTimestampInMillis()) + p0.getValue();
return value - py;
}
}
}
public class Bucket {
private long seconds; // Seconds since 1.1.1970, used as bucket ID
private short millis; // 0-999, used for a more exact calculation
private double value;
public Bucket(long seconds, short millis, double value) {
this.seconds = seconds;
this.millis = millis;
this.value = value;
}
public long getSeconds() {
return seconds;
}
public double getValue() {
return value;
}
public long getTimestampInMillis() {
return seconds * 1000 + millis;
}
public void updateValue(short millis, double value) {
this.millis = millis;
this.value = value;
}
}
An alternative way could have been to use CompositeMeterRegistry on the top level and then add both a PrometheusMeterRegistry and a StepMeterRegistry. Prometheus reports percentiles and Step reports rates. Our monitoring system would then have to query two endpoints.
This was a temporary solution until we modified our monitoring system to read the prometheus endpoint and calculate its own rates.
I am working on a project which deal with heavy data sets. I am using Primefaces 4 & 5, spring and hibernate. I have to to display a very huge datasets such as min 3000 rows with 100 columns with various features such as sorting, filtering, row-expansion etc. My problem is, my applications took 8 to 10 mins to show the whole page as well as other functionalities(sorting, filtering ) also takes a lot time. My client is not happy at all. However I can use pagination for this but again My client do not want paging. So I decided to use livescroll but unfortunately I failed to implement livescroll with lazyload or without lazyload as there were bugs in PF regarding livescroll. also i have posted this question here earlier but no solution found.
This performance issue is very critical and show stopper for me. To show 3000 rows with 100 columns, the size of the page which is getting loaded is ~10MB.
I have calculated the time consumed by various life-cycles of of JSF, using Phase-listener I figure out that its Browser who is taking time to parse the response rendered by jsf. To complete the all phases my application took only 25 sec.
At minimal I want to increase the performance of my project. Please share any idea, suggestion and anything which could help to overcome this problem
Note: There is no database manipulations in getters and setters as well as no complex business logic.
UPDATE :
This is my datatable without lazyload:
<p:dataTable
style="width:100%"
id="cdTable"
selection="#{controller.selectedArray}"
resizableColumns="true"
draggableColumns="true"
var="cd"
value="#{controller.cdDataModel}"
editable="true"
editMode="cell"
selectionMode="multiple"
rowSelectMode="add"
scrollable="true"
scrollHeight="650"
rowKey="#{cd.id}"
rowIndexVar="rowIndex"
styleClass="screenScrollStyle"
liveScroll="true"
scrollRows="50"
filterEvent="enter"
widgetVar="dt4"
>
Here everything is working except filtering. Once I filter then first page is displayed but unable to sort or livescroll on datatable. Note this I have tested in Primefaces5.
2nd Approch
With lazyload with same datatable
1) When I add rows="100" livescroll happens but problem with row-editing, row-expansion but filter & sorting works.
2) When I remove rows livescroll works with row-editing, row-expansion etc but filter & sorting dont work.
My LazyLoadModel is as follows
public class MyDataModel extends LazyDataModel<YData>
{
#Override
public List<YData> load(int first, int pageSize,
List<SortMeta> multiSortMeta, Map<String, Object> filters) {
System.out.println("multisort wala load");
return super.load(first, pageSize, multiSortMeta, filters);
}
/**
*
*/
private static final long serialVersionUID = 1L;
private List<YData> datasource;
public YieldRecBondDataModel() {
}
public YieldRecBondDataModel(List<YData> datasource) {
this.datasource = datasource;
}
#Override
public YData getRowData(String rowKey) {
// In a real app, a more efficient way like a query by rowKey should be
// implemented to deal with huge data
// List<YData> yList = (List<YData>) getWrappedData();
for (YData y : datasource)
{
System.out.println("datasource :"+datasource.size());
if(y.getId()!=null)
{
if (y.getId()==(new Long(rowKey)))
{
return y;
}
}
}
return null;
}
#Override
public Object getRowKey(YData y) {
return y.getId();
}
#Override
public void setRowIndex(int rowIndex) {
/*
* The following is in ancestor (LazyDataModel):
* this.rowIndex = rowIndex == -1 ? rowIndex : (rowIndex % pageSize);
*/
if (rowIndex == -1 || getPageSize() == 0) {
super.setRowIndex(-1);
}
else
super.setRowIndex(rowIndex % getPageSize());
}
#Override
public List<YData> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String,Object> filters) {
List<YData> data = new ArrayList<YData>();
System.out.println("sort order : "+sortOrder);
//filter
for(YData yInfo : datasource) {
boolean match = true;
for(Iterator<String> it = filters.keySet().iterator(); it.hasNext();) {
try {
String filterProperty = it.next();
String filterValue = String.valueOf(filters.get(filterProperty));
Field yField = yInfo.getClass().getDeclaredField(filterProperty);
yField.setAccessible(true);
String fieldValue = String.valueOf(yField.get(yInfo));
if(filterValue == null || fieldValue.startsWith(filterValue)) {
match = true;
}
else {
match = false;
break;
}
} catch(Exception e) {
e.printStackTrace();
match = false;
}
}
if(match) {
data.add(yInfo);
}
}
//sort
if(sortField != null) {
Collections.sort(data, new LazySorter(sortField, sortOrder));
}
int dataSize = data.size();
this.setRowCount(dataSize);
//paginate
if(dataSize > pageSize) {
try {
List<YData> subList = data.subList(first, first + pageSize);
return subList;
}
catch(IndexOutOfBoundsException e) {
return data.subList(first, first + (dataSize % pageSize));
}
}
else
return data;
}
#Override
public int getRowCount() {
// TODO Auto-generated method stub
return super.getRowCount();
}
}
I am fade up with these issues and becomes show stopper for me. Even i tried Primefaces 5
If your data is loaded from db i suggest you to do a better LazyDataModel like:
public class ElementiLazyDataModel extends LazyDataModel<T> implements Serializable {
private Service<T> abstractFacade;
public ElementiLazyDataModel(Service<T> abstractFacade) {
this.abstractFacade = abstractFacade;
}
public Service<T> getAbstractFacade() {
return abstractFacade;
}
public void setAbstractFacade(Service<T> abstractFacade) {
this.abstractFacade = abstractFacade;
}
#Override
public List<T> load(int first, int pageSize, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
PaginatedResult<T> pr = abstractFacade.findRange(new int[]{first, first + pageSize}, sortField, sortOrder, filters);
setRowCount(new Long(pr.getTotalItems()).intValue());
return pr.getItems();
}
}
The service is some kind of backend communication (like an EJB) injected in the ManagedBean that use this model.
The service for pagination may be like this:
#Override
public PaginatedResult<T> findRange(int[] range, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
final Query query = getEntityManager().createQuery("select x from " + entityClass.getSimpleName() + " x")
.setFirstResult(range[0]).setMaxResults(range[1] - range[0] + 1);
// Add filter sort etc.
final Query queryCount = getEntityManager().createQuery("select count(x) from " + entityClass.getSimpleName() + " x");
// Add filter sort etc.
Long rowCount = (Long) queryCount.getSingleResult();
List<T> resultList = query.getResultList();
return new PaginatedResult<T>(resultList, rowCount);
}
Note that you have to do the paginated query (with jpa like this the orm do the query for you, but if you don't use orm have to do paginated query, for oracle look at TOP-N query, for example: http://oracle-base.com/articles/misc/top-n-queries.php)
Remember your return obj must be contains also the total record as a fast count:
public class PaginatedResult<T> implements Serializable {
private List<T> items;
private long totalItems;
public PaginatedResult() {
}
public PaginatedResult(List<T> items, long totalItems) {
this.items = items;
this.totalItems = totalItems;
}
public List<T> getItems() {
return items;
}
public void setItems(List<T> items) {
this.items = items;
}
public long getTotalItems() {
return totalItems;
}
public void setTotalItems(long totalItems) {
this.totalItems = totalItems;
}
}
All this is useful if your database table is correctly setup, pay aptention to the execution plan of the possible query and add the right index.
Hope to give some hint to improve you performance
In the end, remember to your final user that the human eyes can't see more that 10-20 record at once, so it is very useless to have thousand record in a page.
You have used the default load implementation which is used in the showcases of Primefaces. This is not the correct implementation for your case where you load your data from a database.
The load method should use the correct query with consideration of :
1) the filter fields that are used, example:
String query = "select e from Entity e where lower(e.f1) like lower('" + filters.get(key) + "'%) and..., etc. for the other fields
2) the sorting columns that are used, example:
query.append("order by ").append(sortField).append(" ").append(SortOrder.ASCENDING.name() ? "" : sortOrder.substring(0, 4)),..., etc. for the other columns.
3) The total count of your query WITH 1) attached to it. Example:
Long totalCount = (Long) entityManager.createQuery("select count(*) from Entity e where lower(e.f1) like lower('filterKey1%') and lower(e.f2) like lower('filterKey2%') ...").getSingleResult();
using asp.net mvc 4,
I created a class with a static method like this
public class StaticClass
{
public static int val { get; set; }
public static string ReturnValueBasedOnInput(int n)
{
string res;
switch (n)
{
case 101:
Thread.Sleep(30000);
res = "Long lasting response: 101" + val;
break;
default:
res = n.ToString() + " was provided..." + val;
break;
}
return res;
}
}
it is called from my controller :
public ActionResult Index(int id = 1)
{
ViewBag.returnValue = StaticClass.ReturnValueBasedOnInput(id);
return View(id);
}
I expected that when i call the method with a parameter value of 101 the application should be blocked for 30 secs, but it remains responsive. I thought since this is a static method it should be blocked for 30 second for all incoming method calls. can someone explain what happens here?
The thread handling the request to the Index action with id=101 of your controller should be blocked. Threads handling other requests of other sessions will not be blocked. Even other requests for the same session may not be blocked depending on ReadOnly session attribute of corresponding controllers [SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)].
I'm trying to figure out how to manage the whole game loop manually in a Windows game, without using the regular Game Microsoft.Xna.Framework.Game class.
The reason for this is using the regular Game class causes some stuttering in my game. Not much, but because of the specific nature of the game it is still quite visible.
After trying a bunch of different settings (vsync, fixedtimestep, various framerates etc.) I decided to try write my own Game class to have full control of the timing. I am not sure that will fix it, but at least this way I have full control.
Basically I need to:
Set up the game window
In a loop: Do all rendering as usual, and then flush the result to the screen, manage backbuffers etc.
Anyone knows how to do this? It sounds quite easy in fact, but could not find any documentation on how to do it.
Not sure what I am doing wrong, but I have the following code (just for testing, timing will be handled differently), and the loop will run for a little while then stop. Once I pass my mousepointer over the window the loop will run for a little while again.
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Thread.Sleep(500);
//Message message;
//while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
}
If enabling the "while PeekMessage", the loop will run continuously, but ignoring the sleep and also stopping when the mouse is moving over the window. Not sure what is going on here...
I think optimally I would just want to do something simple like this in the main render loop:
while (alive)
{
Thread.Sleep(100);
gametime.update();
Update(gametime);
Draw(gametime);
GraphicsDevice.Present();
}
But in this case the window remains blank, as it seems the window is not actually being redrawn with the new content. I tried a form.Refresh(), but still no go... Any ideas?
(added xbox information)
for windows you Basically need to create a Form and Show it, then store its handle and the form itself.
Using this handle you can create a GraphicsDevice.
Then you hook Application.Idle to your own function that calls your update and render.
For example
public class MyGame
{
public Form form;
public GraphicsDevice GraphicsDevice;
public MyGame()
{
form = new Form();
form.ClientSize = new Size(1280, 1024);
form.MainMenuStrip = null;
form.Show();
}
public void Run()
{
PresentationParameters pp = new PresentationParameters();
pp.DeviceWindowHandle = form.Handle;
pp.BackBufferFormat = SurfaceFormat.Color;
pp.BackBufferWidth = 1280;
pp.BackBufferHeight = 1024;
pp.RenderTargetUsage = RenderTargetUsage.DiscardContents;
pp.IsFullScreen = false;
pp.MultiSampleCount = 16;
pp.DepthStencilFormat = DepthFormat.Depth24Stencil8;
GraphicsDevice = new GraphicsDevice(GraphicsAdapter.DefaultAdapter,
GraphicsProfile.HiDef,
pp);
Application.Idle += new EventHandler(Application_Idle);
Application.Run(form);
}
private void Application_Idle(object pSender, EventArgs pEventArgs)
{
Message message;
while (!PeekMessage(out message, IntPtr.Zero, 0, 0, 0))
{
/* Your logic goes here
Custom timing and so on
Update();
Render();
*/
}
}
void Render()
{
GraphicsDevice.Clear(ClearOptions.DepthBuffer | ClearOptions.Target, Color.Black, 1, 0);
//Your logic here.
GraphicsDevice.Present();
}
[StructLayout(LayoutKind.Sequential)]
private struct Message
{
public IntPtr hWnd;
public int msg;
public IntPtr wParam;
public IntPtr lParam;
public uint time;
public Point p;
}
[return: MarshalAs(UnmanagedType.Bool)]
[SuppressUnmanagedCodeSecurity, DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern bool PeekMessage(out Message msg, IntPtr hWnd, uint
messageFilterMin, uint messageFilterMax, uint flags);
}
EDIT 1
For xbox you may just be able to place your own custom run function with your game loop in a throttled while true loop. Inside that run outside the top of the while true you will probably have to do the graphics device initialization and verification with IntPtr.Zero as your handle
EDIT 2
i use something like this ( got from http://www.koonsolo.com/news/dewitters-gameloop/ )
private long nextGameTick;
private Stopwatch stopwatch;
const int ticksPerSecond = 60;
const int skipTicks = 1000 / ticksPerSecond;
private const int maxSkip = 10;
`constructor
stopwatch = Stopwatch.StartNew();
nextGameTick = stopwatch.ElapsedMilliseconds;
`loop
int loops = 0;
long currentTick = stopwatch.ElapsedMilliseconds;
while ( (ulong)(currentTick - nextGameTick) > skipTicks && loops < maxSkip)
{
Update(16.667f);
nextGameTick += skipTicks;
loops++;
}
PreRender();
Render();
PostRender();
EDIT 3
Creating a content manager was a little more work, but still managable. You need to create a class that implements IServiceProvider. This class takes a GraphicsDevice in its constructor in order to create the next class the implements IGraphicsDeviceProvider. in addition I implement GetService like this
//in implementer of IServiceProvider
public object GetService ( Type serviceType )
{
if ( serviceType == typeof ( IGraphicsDeviceService ) )
{
return myGraphicsService;
}
return null;
}
For convenience i also add a method to the class to create and return managers
//in implementer of IServiceProvider
public ContentManager CreateContentManager( string sPath )
{
ContentManager content = new ContentManager(this);
content.RootDirectory = sPath;
return content;
}
In addition i create a class that implements IGraphicsDeviceService and takes a reference to my GraphicsDevice. then I create a property and field in it like so
//in implementer of IGraphicsDeviceService
private GraphicsDevice graphicsDevice;
public GraphicsDevice GraphicsDevice
{
get
{
return graphicsDevice;
}
}
So the call ends up being somehting like
MyServiceProvider m = new MyServiceProvider(graphicsDevice);
ContentManager content = m.CreateContentManager("Content");
where
MyServiceProvider(GraphicsDevice graphicsDevice)
{
myGraphicsService = new MyGraphicsDeviceService(graphicsDevice);
}
MyGraphicsDeviceService(GraphicsDevice gfxDevice)
{
graphicsDevice = gfxDevice;
}
-Sorry for fragmenting the code around but its not something i wrote too recently so im having difficulty remembering parts.
EDIT 4
i had an odd case with my custom game i just remembered when i new the Form for it i
had to bind
private void IgnoreAlt(object pSender, KeyEventArgs pEventArgs)
{
if (pEventArgs.Alt && pEventArgs.KeyCode != Keys.F4)
pEventArgs.Handled = true;
}
to
form.KeyUp += IgnoreAlt;
form.KeyDown += IgnoreAlt;
otherwise i got some horrible stalls.